在C ++ Primer,第5版,§6.5.2:
constexpr
函数的定义与任何其他函数一样,但必须满足某些限制:返回类型和每个参数的类型必须是文字类型(§2.4.4, p.66),函数体必须只包含一个return语句
但本章中的另一句话(第239页):
允许constexpr函数返回不是常量的值
// scale(arg) is a constant expression if arg is a constant expression constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
这是一个矛盾的总结吗?我很困惑。
scale
的返回类型是文字类型?
更新:
文字类型和常量之间有什么区别?
答案 0 :(得分:8)
首先,我认为作者的意思是constexpr函数不必产生constant expression,这是可以在编译时进行评估的表达式。< / p>
如果函数的参数也是常量表达式,那么constexpr函数只会产生一个常量表达式,而正好说明之后的注释:
// scale(arg) is a constant expression if arg is a constant expression
以及之后的示例也证明了这种行为:
int arr[scale(2)]; // ok: scale(2) is a constant expression
int i = 2; // i is not a constant expression
int a2[scale(i)]; // error: scale(i) is not a constant expression
在C ++中(而不是C99 ),因为数组大小必须是常量表达式,因此最后一种情况是错误,因为参数为scale
不是一个恒定的表达。
这是与函数的返回类型不同的概念,它必须是literal type,它是以下任何一种:
答案 1 :(得分:6)
这并不矛盾。除了强制返回类型必须是“文字类型”之外,草案标准还规定对constexpr
函数的调用不必出现在常量表达式中。来自C ++ 11标准草案:
§7.1.5/ 7对
constexpr
函数的调用产生与...相同的结果 在所有方面调用等效的非constexpr
函数 除了对constexpr
函数的调用可以出现在常量中 表达
答案 2 :(得分:0)
constexpr什么都不做,只是告诉编译器在编译时这个值是存在的,所以你可以将它用作模板参数(例如)
int a1 = 5;
std::array<int, a1> arr1; // error, a is variable
const int a2 = 5;
std::array<int, a2> arr2; // OK
int f1() { return 3; }
std::array<int, f1()> arr3; // error, compiler doesn't know it is const 3
constexpr int f2() { return 3; }
std::array<int, f2()> arr4; // OK
稍后你也可以:
constexpr int f3() { return f1() + 1; } // error, f1 is not constexpr
constexpr int f4() { return f2() + 1; } // OK
std::array<int, f4()> arr5; // OK
现在关于文字类型限制:函数参数和结果类型应该是文字类型(Need clarification on definition of literal type),与模板参数适用的限制相同(在编译类型中已知)。
constexpr std::string f5() { return "hello"; } // error,
// std::string is not literal type
constexpr const std::string& f6() {
static const std::string s = "hello";
return s;
}
template<const std::string& s> SomeClass { ... };
SomeClass<f6()> someObject;