是否有一种非间接、非 hack 的方法来保证 constexpr 函数只能在编译时调用?

Is there a non-indirection, non-hack way to guarantee that a constexpr function only be callable at compile time?

目前,我们有两个主要的编译时评估选项:模板元编程(通常使用模板结构 and/or 变量)和 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.

有可能 , but this guarantee breaks if the function is accessed directly instead of through the indirection helpers (as noted in the linked answer's comments). It is also possible to such that calling it at runtime becomes impossible, by throwing an undefined symbol,从而通过笨拙的 hack 提供此保证。然而,这些似乎都不是最佳选择。


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

1:宏技术上也是一个选项,但是......是的,不。

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