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 arytmetycznychPytanie: 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; }