有没有一种非间接,非破解的方法来保证constexpr函数只能在编译时调用?

Jus*_*ica 6 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.
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

由于模板的编译时性质,我们还可以保证前三个在编译时可评估;但是,我们不能为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.
Run Code Online (Sandbox Code Playgroud)

可以使用间接来提供有效的保证,即constexpr只能在编译时调用给定的函数,但是如果直接访问该函数而不是通过间接帮助器(如链接的答案的注释中所述),则此保证会失效。它也可以毒死一constexpr功能,使得调用它在运行时变得不可能,throw荷兰国际集团未定义的符号,从而提供这种保证的尴尬黑客。然而,这些似乎都不是最优的。


考虑到这一点,我的问题因此是:包括当前标准,C ++ 20草案,正在考虑的提案,实验性功能以及任何其他种类,有没有办法仅使用功能就可以提供这种保证而无需求助于黑客或间接访问语言本身内置和/或正在考虑的工具?[例如,诸如(理论上的)[[compile_time_only]]std :: is_constant_evaluated的[[no_runtime]]用法或概念之类的属性?)

1:从技术上讲,宏也是一种选择,但是...是的,不是。

Nat*_*ica 10

consteval为此添加了C ++ 20 。一个consteval函数是一个constexpr这是保证只称为在编译时功能。