在 C++11 中,我们得到constexpr
:
constexpr int foo (int x) {
return x + 1;
}
是否可以使用编译时错误foo
的动态值进行调用?x
也就是说,我想创建一个foo
只能传入constexpr
参数的对象。
将其替换为元函数:
template <int x> struct foo { static constexpr int value = x + 1; };
用法:
foo<12>::value
不幸的是,constexpr
除非绝对必要,否则无法保证编译器会评估一个函数,即使是最微不足道的函数。也就是说,除非它出现在编译时需要其值的地方,例如在模板中。为了强制编译器在编译期间进行评估,您可以执行以下操作:
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 */
不太好的事情是它需要一个宏,但如果你想要保证编译时评估和漂亮的代码,这似乎是目前不可避免的。(不过我很想被证明是错的!)
我会使用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
是的,它现在可以在纯粹的惯用 C++ 中完成,因为 C++20 增加了对此类问题的支持。您使用consteval
并可以确保在编译期间对其进行评估的函数。https://en.cppreference.com/w/cpp/language/consteval
consteval int foo( int x ) {
return x + 1;
}
int main( int argc, char *argv[] )
{
return foo( argc ); // This will not compile
return foo( 1 ); // This works
}
另请参阅3 个最相关的编译器中的这个 godbolt.org 演示。