占位符类型说明符 (C++11 起)
占位符类型说明符指定一个占位符类型,该类型将在稍后被替换,通常通过从初始化器中推导出来。
目录 |
[编辑] 语法
类型约束 (可选) auto |
(1) | ||||||||
类型约束 (可选) decltype(auto) |
(2) | (C++14 起) | |||||||
类型约束 | - | (C++20 起)一个概念名,可选地限定,可选地后跟用<> 括起来的模板参数列表 |
占位符auto可以伴随修饰符,例如const或&
,它们将参与类型推导。占位符decltype(auto)必须是声明类型的唯一组成部分。(C++14 起)
如果存在类型约束,令
如果约束表达式无效或返回false,则推导失败。 |
(C++20 起) |
[编辑] 说明
占位符类型说明符可以出现在以下语境中:
参数声明在以下参数声明中,所声明参数的类型可以采用语法(1)
|
(C++14 起) |
|
(C++17 起) |
(C++20 起) |
[编辑] 函数声明
占位符类型可以出现在包含尾随返回类型的函数声明符的声明说明符中。
(C++14 起) |
auto f() -> int; // OK: f returns int auto g() { return 0.0; } // OK since C++14: g returns double auto h(); // OK since C++14: h’s return type will be deduced when it is defined
[编辑] 变量声明
使用占位符类型声明的变量的类型从其初始化器推导。此用法允许在变量的初始化声明中。
占位符类型只能作为声明说明符序列中的声明说明符之一,或作为尾随返回类型中的类型说明符之一,该尾随返回类型指定替换此类声明说明符的类型。在这种情况下,声明必须声明至少一个变量,并且每个变量必须具有非空初始化器。
// “auto”s in declaration specifiers auto x = 5; // OK: x has type int const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int static auto y = 0.0; // OK: y has type double auto f() -> int; auto (*fp)() -> auto = f; // OK: the “auto” in the trailing return type // can be deduced from f
结构化绑定声明auto说明符可以用于结构化绑定声明中。 |
(C++17 起) |
[编辑] new 表达式
占位符类型可以用于new 表达式的 type-id 的类型说明符序列中。在此类 type-id 中,占位符类型必须作为类型说明符序列中的类型说明符之一,或作为尾随返回类型,该尾随返回类型指定替换此类类型说明符的类型。
函数式转换auto类型说明符可用作函数式转换的类型说明符。 |
(C++23 起) |
[编辑] 注意
在 C++11 之前,auto具有存储期说明符的语义。
在上述未明确说明的上下文中使用占位符类型的程序是格式错误的。
如果一个声明声明了多个实体,并且声明说明符序列使用了占位符类型,则如果满足以下任何条件,程序将格式错误:
- 声明的某些实体不是变量。
- 在每次推导中,替换占位符类型的类型不相同。
auto f() -> int, i = 0; // Error: declares a function and a variable with “auto” auto a = 5, b = {1, 2}; // Error: different types for “auto”
auto关键字也可以在嵌套名称说明符中使用。形式为auto::的嵌套名称说明符是一个占位符,它根据受约束类型占位符推导的规则被类或枚举类型替换。 |
(概念 TS) |
功能测试宏 | 值 | 标准 | 特性 |
---|---|---|---|
__cpp_decltype_auto |
201304L |
(C++14) | decltype(auto) |
[编辑] 关键词
[编辑] 示例
#include <iostream> #include <utility> template<class T, class U> auto add(T t, U u) { return t + u; } // the return type is the type of operator+(T, U) // perfect forwarding of a function call must use decltype(auto) // in case the function it calls returns by reference template<class F, class... Args> decltype(auto) PerfectForward(F fun, Args&&... args) { return fun(std::forward<Args>(args)...); } template<auto n> // C++17 auto parameter declaration auto f() -> std::pair<decltype(n), decltype(n)> // auto can't deduce from brace-init-list { return {n, n}; } int main() { auto a = 1 + 2; // type of a is int auto b = add(1, 1.2); // type of b is double static_assert(std::is_same_v<decltype(a), int>); static_assert(std::is_same_v<decltype(b), double>); auto c0 = a; // type of c0 is int, holding a copy of a decltype(auto) c1 = a; // type of c1 is int, holding a copy of a decltype(auto) c2 = (a); // type of c2 is int&, an alias of a std::cout << "before modification through c2, a = " << a << '\n'; ++c2; std::cout << " after modification through c2, a = " << a << '\n'; auto [v, w] = f<0>(); //structured binding declaration auto d = {1, 2}; // OK: type of d is std::initializer_list<int> auto n = {5}; // OK: type of n is std::initializer_list<int> // auto e{1, 2}; // Error as of DR n3922, std::initializer_list<int> before auto m{5}; // OK: type of m is int as of DR n3922, initializer_list<int> before // decltype(auto) z = { 1, 2 } // Error: {1, 2} is not an expression // auto is commonly used for unnamed types such as the types of lambda expressions auto lambda = [](int x) { return x + 3; }; // auto int x; // valid C++98, error as of C++11 // auto x; // valid C, error in C++ [](...){}(c0, c1, v, w, d, n, m, lambda); // suppresses "unused variable" warnings }
可能的输出
before modification through c2, a = 3 after modification through c2, a = 4
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 1265 | C++11 | auto说明符可用于声明带尾随返回类型的函数并在一个声明语句中定义变量。 返回类型并在一个声明语句中定义变量 |
已禁止 |
CWG 1346 | C++11 | 带括号的表达式列表不能赋值给auto变量 | 允许 |
CWG 1347 | C++11 | 带有auto说明符的声明可以定义两个变量 分别为类型 T 和std::initializer_list<T> |
已禁止 |
CWG 1852 | C++14 | decltype(auto)中的auto说明符也是占位符 | 不是占位符 在这种情况下 |
CWG 1892 | C++11 | 函数指针 type-id 的返回类型可以是auto | 已禁止 |
CWG 2476 | C++11 | CWG 问题 1892 的解决方案禁止从初始化器推导函数指针变量的返回类型。 从初始化器推导函数指针变量的返回类型 |
允许 |
[编辑] 参考资料
- C++23 标准 (ISO/IEC 14882:2024)
- 9.2.9.6 占位符类型说明符 [dcl.spec.auto]
- C++20 标准 (ISO/IEC 14882:2020)
- 9.2.8.5 占位符类型说明符 [dcl.spec.auto]
- C++17 标准 (ISO/IEC 14882:2017)
- 10.1.7.4
auto
说明符 [dcl.spec.auto]
- 10.1.7.4
- C++14 标准 (ISO/IEC 14882:2014)
- 7.1.6.4
auto
说明符 [dcl.spec.auto]
- 7.1.6.4
- C++11 标准 (ISO/IEC 14882:2011)
- 7.1.6.4
auto
说明符 [dcl.spec.auto]
- 7.1.6.4