【发布时间】:2019-11-26 19:07:51
【问题描述】:
目前,我们有两个主要的编译时评估选项:模板元编程(通常使用模板结构和/或变量)和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 是可能的,但如果直接访问函数而不是通过间接帮助程序(如链接答案的 cmets 中所述)访问该函数,则此保证会失效。也可以poison a constexpr function 这样在运行时调用它就变得不可能了,by throwing an undefined symbol,因此通过笨拙的 hack 提供了这种保证。然而,这些似乎都不是最佳选择。
考虑到这一点,我的问题是:包括当前标准、C++20 草案、正在考虑的提案、实验性功能以及任何其他类似的东西,有没有一种方法可以在不诉诸黑客或间接手段的情况下提供这种保证,仅使用内置和/或考虑内置到语言本身的功能和工具? [例如,一个属性,如(理论)[[compile_time_only]] 或[[no_runtime]],std::is_constant_evaluated 的用法,或者一个概念,也许?]
1:宏技术上也是一种选择,但是...是的,不。
【问题讨论】:
-
注意:可能与c++ - What is consteval? 重复,我不知道该问题或其与我自己的相关性。