2013-07-15 39 views
6

In C++ 11 otteniamo constexpr:Imporre fase di compilazione constexpr

constexpr int foo (int x) { 
    return x + 1; 
} 

E 'possibile effettuare le chiamate di foo con un valore dinamico di x un errore di tempo di compilazione? Cioè, voglio creare un foo tale da poter passare solo gli argomenti constexpr.

+1

si può sempre trasformare in un modello di funzione: 'template int foo() {return x + 1; } ' –

+1

Si noti che' constexpr' è stato parzialmente chiamato in essere per neutralizzare tutti i workaround sintattici che si vedranno nelle risposte qui. – rubenvb

+0

'#define foo (N) pippo ()' mi sembra praticabile. –

risposta

8

Sostituirlo con un metafunction:

template <int x> struct foo { static constexpr int value = x + 1; }; 

Usage:

foo<12>::value 
+0

O meglio, dargli un 'operatore()' in modo che assomigli a una chiamata di funzione. – rubenvb

+0

@rubenvb: Ancora meglio, usa un modello di variabile: 'modello int bar = pippo :: valore;'. Utilizzo: 'bar <12>'. Disponibile in C++ 14. –

+0

Oh ....... Kewl. – rubenvb

0

userei static_assert come mostrato in questo esempio

#include<iostream> 

constexpr int foo(int x) { 
     return x+1; 
} 

int main() { 
     // Works since its static 
     std::cout << foo(2) << std::endl; 
     static_assert(foo(2) || foo(2) == 0, "Not Static"); 

     // Throws an compile error 
     int in = 3; 
     std::cout << foo(in) << std::endl; 
     static_assert(foo(in) || foo(in) == 0, "Not Static"); 
} 

Per maggiori informazioni: http://en.cppreference.com/w/cpp/language/static_assert

+0

Non ho un compilatore ATM con 'constexpr', ma questa idea non sarebbe estesa a mettere' static_assert' direttamente in 'foo'? Per esempio. 'constexpr int foo (int x) {static_assert (x == x," Not Static "); return x + 1; } ' –

+1

@ThomasEding. Si potrebbe, ma poi si perderebbe la flessibilità di utilizzare la stessa funzione della funzione valutata in fase di esecuzione. Dal momento che 'static_assert' ha verificato al momento della compilazione, non influirà anche sul runtime. –

2

Sfortunatamente, non è possibile garantire che una funzione constexpr, anche la più banale, venga valutata dal compilatore a meno che non sia assolutamente necessario. Cioè, a meno che non appaia in un punto in cui il suo valore è richiesto al momento della compilazione, ad es. in un modello. Per far valere il compilatore a fare la valutazione durante la compilazione, è possibile effettuare le seguenti operazioni:

constexpr int foo_implementation (int x) { 
    return x + 1; 
} 

#define foo(x) std::integral_constant<int, foo_implementation(x)>::value 

e quindi utilizzare foo nel codice come al solito

int f = foo(123); 

La cosa bella di questo approccio è che garantisce compilazione tempo di valutazione, e si otterrà un errore di compilazione se si passa una variabile run-time per foo:

int a = 2; 
int f = foo(a); /* Error: invalid template argument for 'std::integral_constant', 
        expected compile-time constant expression */ 

Il non così la cosa bella è che richiede una macro, ma questo sembra al momento inevitabile se si vuole sia una valutazione garantita in fase di compilazione sia un bel codice. (! Mi piacerebbe essere smentiti però)

Problemi correlati