In G ++, varie funzioni matematiche incorporate sono constexpr in determinate condizioni. Ad esempio, le seguenti compilazioni:__builtin_round non è un'espressione costante
static constexpr double A = __builtin_sqrt(16.0);
static constexpr double B = __builtin_pow(A, 2.0);
Non sono sempre constexpr, tuttavia, dipende dall'argomento. Ad esempio, __builtin_sqrt(NAN)
genera un errore di compilazione quando viene utilizzato come espressione costante.
Ma mi colpisce uno strano caso in cui mi sembra che dovrebbe essere constexpr, ma non è così:
static constexpr double value() { return 1.23; }
static constexpr double result = __builtin_round(__builtin_sqrt(value()));
Questo produce:
a.cpp:2:73: error: ‘__builtin_round(1.1090536506409416e+0)’ is not a constant expression
static constexpr double result = __builtin_round(__builtin_sqrt(value()));
^
Ho provato varianti del codice sopra, e ho trovato che:
- Il
__builtin_round
ha un ruolo speciale nel problema. Sostituendolo con qualche altra funzione matematica incorporata, come ad esempiosqrt
opow
, si risolve l'errore. Sembrerebbe quindi che il__builtin_round
manchi semplicemente del supporto di constexpr. Ma ... - Se
value()
è sostituito da un valore letterale1.23
, anche questo rimuove l'errore. - La rimozione di
__builtin_sqrt
, lasciando solo__builtin_round(value())
, rimuove anche l'errore.
Mi piacerebbe sapere perché il round
si comporta in questo modo e se c'è qualche soluzione.
NOTA. Sono consapevole del fatto che le funzioni matematiche incorporate, con la loro consorteprecisione, sono una caratteristica specifica del compilatore non standard. Per favore, non darmi lezioni su come non dovrei usarlo, o su come non dovrei provare a fare matematica matematica in fase di compilazione. Nel mio caso, avere la matematica di constexpr è una caratteristica importante, e sto bene a seconda di G ++.
L'arrotondamento non dipende dal metodo di arrotondamento in virgola mobile corrente, che è noto solo in fase di esecuzione? –
@AlanStokes Ho insegnato anch'io, ma gcc presuppone comunque che la modalità di arrotondamento sia nota al momento della compilazione. Vedi l'opzione '-fno-rounding-math' in gcc. Inoltre, se fosse dovuto a ciò, almeno in teoria praticamente tutti gli operatori FP non sarebbero constexpr (che, almeno in G ++, sono constexpr, simili alla maggior parte delle funzioni matematiche). –