是否有非间接,非破解的方法来保证constexpr函数仅在编译时可调用?

时间:2019-07-17 21:51:17

标签: c++ constexpr

目前,我们有两个主要的编译时评估选项:模板元编程(通常使用模板结构和/或变量)和constexpr操作 1

template<int l, int r> struct sum_ { enum { value = l + r }; }; // With struct.
template<int l, int r> const int sum = sum_<l, r>::value;       // With struct & var.
template<int l, int r> const int sub = l - r;                   // With var.
constexpr int mul(int l, int r) { return l * r; }               // With constexpr.

其中,我们保证可以在编译时对所有这四个值进行评估。

template<int> struct CompileTimeEvaluable {};

CompileTimeEvaluable<sum_<2, 2>::value> template_struct;                 // Valid.
CompileTimeEvaluable<sum<2, 2>>         template_struct_with_helper_var; // Valid.
CompileTimeEvaluable<sub<2, 2>>         template_var;                    // Valid.
CompileTimeEvaluable<mul(2, 2)>         constexpr_func;                  // Valid.

由于模板的编译时性质,我们还可以保证前三个仅在编译时可评估。但是,我们无法为constexpr函数提供相同的保证。

int s1 = sum_<1, 2>::value;
//int s2 = sum_<s1, 12>::value; // Error, value of i not known at compile time.

int sv1 = sum<3, 4>;
//int sv2 = sum<s1, 34>;        // Error, value of i not known at compile time.

int v1 = sub<5, 6>;
//int v2 = sub<v1, 56>;         // Error, value of i not known at compile time.

int c1 = mul(7, 8);
int c2 = mul(c1, 78);           // Valid, and executed at run time.

可以use indirection to provide an effective guarantee that a given constexpr function can only be called at compile time,但是如果直接访问该函数而不是通过间接帮助器(如链接的答案的注释中所述),则此保证将失效。 poison a constexpr function也有可能无法在运行时调用by throwing an undefined symbol,从而通过笨拙的破解提供了这种保证。但是,这些都不是最佳选择。


考虑到这一点,我的问题是:包括当前的标准,C ++ 20草案,正在考虑的提案,实验性功能以及其他类似的东西,有没有办法提供这种保证,而不必借助黑客或间接手段,仅使用内置和/或考虑内置到语言本身中的功能和工具? [例如,诸如(理论上的)[[compile_time_only]][[no_runtime]]之类的属性,std::is_constant_evaluated的用法或一个概念,也许?]

1:宏在技术上也是 ,但是...是的,不是。

1 个答案:

答案 0 :(得分:9)

C ++ 20为此目的添加了constevalconsteval函数是一个constexpr函数,保证只能在编译时调用。