Considerare una semplice classe int Wrapper
con moltiplicazione sovraccaricata operator*=
e operator*
. Per il sovraccarico dell'operatore "vecchio stile", è possibile definire operator*
in termini di operator*=
e ci sono anche librerie come Boost.Operators e la sua moderna incarnazione df.operators di @DanielFrey che riducono il boilerplate per voi.Linee guida per fare il sovraccarico dell'operatore di constexpr?
Tuttavia, per i calcoli in fase di compilazione utilizzando il nuovo C++ 11 constexpr
, questa convenienza scompare. Un constexpr operator*
non può chiamare operator*=
perché quest'ultimo modifica il suo argomento (implicito) a sinistra. Inoltre, c'è no overloading on constexpr, quindi aggiungere constexpr operator*
in più ai risultati esistenti di operator*
in un'ambiguità di risoluzione del sovraccarico.
Il mio approccio attuale è:
#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
}
Live output here. I miei problemi con questo sono:
- duplicazione della logica moltiplicazione sia
operator*=
eoperator*
, invece dioperator*
essere espresso in termini dioperator*=
- quindi, Boost.Operators non funziona più per ridurre il boilerplate per la scrittura di molti altri operatori aritmetici
domanda: è questo modo di avere sia un runtime operator*=
e misti runtime raccomandata C++ 11/fase di compilazione 01.237.? C++ 14 modifica qualsiasi cosa qui ad es. ridurre la duplicazione logica?
UPDATE: La risposta da @AndyProwl è accettata come idiomatica, ma come da suggerimento di @DyP, in C++ 11 uno potrebbe ridurre la duplicazione logica a scapito di un incarico in più e lo stile intuitivo
// define operator*= in terms of operator*
Wrap& operator*=(Wrap const& rhs)
{ *this = *this * rhs; return *this; }
Qual è il tuo utilizzo per un sovraccarico "regolare" se può essere "constexpr"? IIRC 'constexpr' si degraderà con grazia a _runtime execution_ nel contesto non-'constexpr'. – sehe
@sehe non si può avere un operatore 'constexpr * =', e quindi 'operatore constexpr *' non può chiamare questo, e invece ha bisogno di duplicare la logica di estrazione dei campi ecc. – TemplateRex
Ah, sto iniziando a vedere la tua vera domanda. Non è *** di avere sovraccarichi non di 'constexpr' (non ne hai bisogno!) Ma piuttosto di non essere in grado di condividere codice perché '* =' non può essere 'constexpr'.Per fortuna ho già fatto +1 su buona fede :) – sehe