2013-07-15 87 views
6

在C++ 11我們得到constexpr強制編譯時constexpr

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

是否有可能使foo調用與x編譯時錯誤動態值?也就是說,我想創建一個foo,這樣只能通過constexpr參數。

+1

你可以隨時把它變成一個函數模板:'template int foo(){return x + 1; }' –

+1

請注意,'constexpr'被部分調用來抵消所有您將在答案中看到的語法解決方法。 (#) – rubenvb

+0

'#define foo(N)foo ()'看起來可行。 –

回答

8

與元函數替換它:

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

用法:

foo<12>::value 
+0

或者更好,給它一個'operator()',以便類似於函數調用。 – rubenvb

+0

@rubenvb:更好的是,使用可變模板:'template int bar = foo :: value;'。用法:'酒吧<12>'。可用於C++ 14。 –

+0

哦....... Kewl。 – rubenvb

0

我會用static_assert如本例所示

#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"); 
} 

更多的相關信息:http://en.cppreference.com/w/cpp/language/static_assert

+0

我沒有帶'constexpr'的編譯器ATM,但是這個想法是否延伸到將'static_assert'直接放到'foo'中?例如。 'constexpr int foo(int x){static_assert(x == x,「Not Static」);返回x + 1; }' –

+1

@ThomasEding。你可以,但是你會失去使用與運行時評估函數相同功能的靈活性。由於在編譯時檢查了'static_assert',它也不會影響運行時。 –

2

不幸的是,除非絕對必要,否則無法保證編譯器會評估函數,即使是最微不足道的函數。也就是說,除非它出現在編譯時需要它的值的地方,例如在模板中。爲了強制編譯器在編譯過程中做了評價,你可以做到以下幾點:

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

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

,然後在你的代碼像往常一樣

使用 foo
int f = foo(123); 

這種方法的好處是,它保證了編譯時的評價,如果你通過一個運行時變量foo,你會得到一個編譯錯誤:

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

不那麼好的一點是它需要一個宏,但如果你希望保證編譯時評估和漂亮的代碼,這似乎是不可避免的。 (我很想被證明是錯誤的!)