c++ - Guidelines to do constexpr operator-overloading? -


consider simple int wrapper class overloaded multiplication operator*= , operator*. "old-style" operator-overloading, 1 can define operator* in terms of operator*=, , there libraries boost.operators , modern incarnation df.operators @danielfrey reduce boilerplate you.

however, compile-time computations using new c++11 constexpr, convenience disappears. constexpr operator* cannot call operator*= because latter modifies (implicit) left argument. furthermore, there no overloading on constexpr, adding constexpr operator* existing operator* results in overload resolution ambiguity.

my current approach is:

#include <iostream>  struct wrap {     int value;          wrap& operator*=(wrap const& rhs)      { value *= rhs.value; return *this; }      // need comment function because of overloading ambiguity 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 able 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 } 

live output here. problems are:

  • duplication of multiplication logic in both operator*= , operator*, instead of operator* being expressed in terms of operator*=
  • hence, boost.operators no longer works reduce boilerplate writing many other arithmetic operators

question: recommended c++11 way of having both run-time operator*= , mixed run-time/compile-time constexpr operator*? c++14 change here e.g. reduce logic duplication?

update: answer @andyprowl accepted idiomatic per suggestion of @dyp, in c++11 1 could reduce logic duplication @ expense of assignment , counter-intuitive style

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

i not find idiomatic solution c++11 (although workaround, dyp's suggestion seems acceptable me).

in c++14 however, constexpr not imply const (see annex c.3.1 of c++14 standard draft n3690), define both operator *= , operator * constexpr, , define latter in terms of former, usual:

struct wrap {     int value;          constexpr wrap& operator *= (wrap const& rhs)      { value *= rhs.value; return *this; }      friend constexpr wrap operator * (wrap const& lhs, wrap const& rhs)     { return wrap(lhs) *= rhs; }     }; 

here live example, above program being compiled -std=c++1y on clang - unfortunately, gcc not seem implement rule yet.


Comments