我一直在用一个SVN构建的笨蛋来混乱,试验一下松弛的constexpr规则.我一直无法确定的一个事情是,是否可以在一个constexpr函数的编译时循环遍历元组元素.
因为我没有符合C14标准的库进行测试,所以我已经准备了以下等效的测试:
template<int N> constexpr int foo() { return N; } constexpr int getSum() { auto sum = 0; for (auto i = 0; i < 10; ++i) { sum += foo<i>(); } return sum; } constexpr auto sum = getSum();
这里有趣的部分是foo< i>().在非constexpr函数中,我希望这无法编译,因为您根本不能使用运行时的int来生成模板的编译时实例化.因为这是一个constexpr函数,我怀疑这是否可能.特别是,在编译时,该值是已知的,即使允许变更.
我知道以下代码将编译:
constexpr auto nValue = 2; foo<nValue>();
在SVN clang中,我的第一个例子不是:
test2.cpp:19:12: error: no matching function for call to 'foo' sum += foo(); ^~~~~~ test2.cpp:11:15: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'N' constexpr int foo() { ^
对于初学者,我很难解释这个错误信息的第二部分.除此之外,它是否受到C14标准的授权,如果是这样,有没有人知道为什么不允许这种语法(简单的监督或防止某些东西)?
解决方法
That aside,is it mandated by the C++14 standard,and if so,does anyone know why this Syntax wouldn’t be allowed (simple oversight or to protect against something)?
这是因为constexpr不是编译时计算或使用的排他性.一个constexpr函数就是在一个常量表达式中使用一个函数(或变量).除此之外,它们是常规功能.在某些上下文(例如static_assert或数组大小等)中,常常表达式仅仅是编译时的情况.
你会在你的代码中注意到你循环一个变量,但你自己循环的变量不是constexpr,所以它不是一个常量表达式,用于N的模板实例化.因为它是没有不同于在这11 C:
constexpr bool f(int x) { static_assert(x > 10,"..."); // invalid return true; }
这显然是无效的,因为如前所述,您不必在独占的编译时情况下使用constexpr函数.例如,没有什么阻止你这样做:
constexpr int times_ten(int x) { return x * 10; } int main() { int a = times_ten(20); // notice,not constexpr static_assert(times_ten(20) == 200,"..."); static_assert(a == 200,"..."); // doesn't compile }