我对 constexpr 函数感到困惑?
I am confused about a constexpr function?
在 C++ Primer 中,第五版,§6.5.2:
A constexpr
function is defined like any other function but must meet certain restrictions: The return type and the type of each parameter in must be a literal type (§2.4.4, p. 66), and the function body must contain exactly one return statement
但本章(第239页)中的另一句话:
A constexpr function is permitted to return a value that is not a constant
// scale(arg) is a constant expression if arg is a constant expression
constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
这是一个矛盾的总结吗?我对此感到困惑。
scale
的return类型是文字类型?
更新:
文字类型和常量有什么区别?
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;
这并不矛盾。除了强制 return 类型必须是 "literal type" 之外,标准草案还规定对 constexpr
函数的调用不必出现在常量表达式中。来自 C++11 标准草案:
§7.1.5/7 A call to a constexpr
function produces the same result as
a call to a equivalent non-constexpr
function in all respects
except that a call to a constexpr
function can appear in a constant
expression.
首先,我认为作者的意思是 constexpr 函数不必产生 constant expression,这是一个 可以 计算的表达式在编译时。
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
的参数不是常量表达式。
这与函数的 return 类型的概念不同,后者必须是 literal type,它是以下任何一种:
- void(since c++14)(因此 constexpr 函数可以 return void)
- 标量类型,包括算术类型、枚举类型、指针类型、指向成员类型的指针,std::nullptr_-
t 和这些类型的 cv 限定版本)
- 引用类型
- 文字类型数组
- class 具有以下所有属性的类型:
- 有一个普通的析构函数,
- 是
- 聚合类型
- 一种至少有一个不是复制或移动构造函数的 constexpr(可能是模板)构造函数的类型
- 所有非静态数据成员和基础 classes 都是非易失性文字类型。
在 C++ Primer 中,第五版,§6.5.2:
A
constexpr
function is defined like any other function but must meet certain restrictions: The return type and the type of each parameter in must be a literal type (§2.4.4, p. 66), and the function body must contain exactly one return statement
但本章(第239页)中的另一句话:
A constexpr function is permitted to return a value that is not a constant
// scale(arg) is a constant expression if arg is a constant expression constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
这是一个矛盾的总结吗?我对此感到困惑。
scale
的return类型是文字类型?
更新:
文字类型和常量有什么区别?
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;
这并不矛盾。除了强制 return 类型必须是 "literal type" 之外,标准草案还规定对 constexpr
函数的调用不必出现在常量表达式中。来自 C++11 标准草案:
§7.1.5/7 A call to a
constexpr
function produces the same result as a call to a equivalent non-constexpr
function in all respects except that a call to aconstexpr
function can appear in a constant expression.
首先,我认为作者的意思是 constexpr 函数不必产生 constant expression,这是一个 可以 计算的表达式在编译时。
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
的参数不是常量表达式。
这与函数的 return 类型的概念不同,后者必须是 literal type,它是以下任何一种:
- void(since c++14)(因此 constexpr 函数可以 return void)
- 标量类型,包括算术类型、枚举类型、指针类型、指向成员类型的指针,std::nullptr_- t 和这些类型的 cv 限定版本)
- 引用类型
- 文字类型数组
- class 具有以下所有属性的类型:
- 有一个普通的析构函数,
- 是
- 聚合类型
- 一种至少有一个不是复制或移动构造函数的 constexpr(可能是模板)构造函数的类型
- 所有非静态数据成员和基础 classes 都是非易失性文字类型。