Wytyczne dotyczące przeciążania operatora constexpr?

Rozważmy prosty intWrapper klasa z przeciążonym mnożeniemoperator*= ioperator*. Dla przeciążenia operatora w starym stylu można zdefiniowaćoperator* pod względemoperator*=i są nawet takie bibliotekiBoost.Operators i jego współczesne wcieleniedf.operators przez @DanielFrey, który redukuje dla ciebie szablon.

Jednak w przypadku obliczeń w czasie kompilacji przy użyciu nowego C ++ 11constexpr, ta wygoda znika. ZAconstexpr operator* nie można zadzwonićoperator*= ponieważ ten ostatni modyfikuje swój (niejawny) lewy argument. Ponadto jestbrak przeciążania na constexpr, więc dodając dodatkoweconstexpr operator* do istniejącegooperator* powoduje niejednoznaczność rozdzielczości przeciążenia.

Moje obecne podejście to:

#include <iostream>

struct Wrap
{
    int value;    

    Wrap& operator*=(Wrap const& rhs) 
    { value *= rhs.value; return *this; }

    // need to comment this function because of overloading ambiguity with the constexpr version
    // friend Wrap operator*(Wrap const& lhs, Wrap const& rhs)
    // { return Wrap { lhs } *= rhs; }    

    friend constexpr Wrap operator*(Wrap const& lhs, Wrap const& rhs)
    { return { lhs.value * rhs.value }; }
};

constexpr Wrap factorial(int n)
{
    return n? factorial(n - 1) * Wrap { n } : Wrap { 1 };    
}

// want to be able to statically initialize these arrays
struct Hold
{
    static constexpr Wrap Int[] = { factorial(0), factorial(1), factorial(2), factorial(3) };
};

int main() 
{
    std::cout << Hold::Int[3].value << "\n"; // 6
    auto w = Wrap { 2 };
    w *= Wrap { 3 };
    std::cout << w.value << "\n"; // 6
}

Tutaj na żywo. Moje problemy z tym to:

duplikacja logiki mnożenia w obuoperator*= ioperator*, zamiastoperator* wyrażone w kategoriachoperator*=stąd Boost.Operators nie działa już, aby zredukować szablon do pisania wielu innych operatorów arytmetycznych

Pytanie: czy jest to zalecany sposób C ++ 11 na posiadanie obu czasów wykonaniaoperator*= i mieszany czas wykonywania / kompilacjaconstexpr operator*? Czy C ++ 14 coś tutaj zmienia, np. zmniejszyć duplikację logiki?

AKTUALIZACJA: Odpowiedź @AndyProwl jest akceptowana jako idiomatyczna, ale zgodnie z sugestią @DyP, w C ++ 11 onemógłby zmniejszyć duplikację logiki kosztem dodatkowego przypisania i stylu anty-intuicyjnego

    // define operator*= in terms of operator*
    Wrap& operator*=(Wrap const& rhs) 
    { *this = *this * rhs; return *this; }

questionAnswers(1)

yourAnswerToTheQuestion