占位符类型说明符 (自 C++11 起)
占位符类型说明符指定一个将在以后替换的占位符类型,通常通过从初始化程序推断得出。
内容 |
[编辑] 语法
type-constraint (可选) auto |
(1) | ||||||||
type-constraint (可选) decltype(auto) |
(2) | (自 C++14 起) | |||||||
type-constraint | - | (自 C++20 起) 一个概念名称,可选限定,可选后跟用 <> 括起来的模板参数列表 |
占位符 auto 可以伴随修饰符,例如 const 或 &
,它们将参与类型推断。 占位符 decltype(auto) 必须是声明类型的唯一组成部分。(自 C++14 起)
如果存在 type-constraint,则令
如果约束表达式无效或返回 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) |
功能测试宏 | 值 | Std | 功能 |
---|---|---|---|
__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++ 标准。
DR | 应用于 | 发布的行为 | 正确行为 |
---|---|---|---|
CWG 1265 | C++11 | auto 说明符可用于声明具有尾随 返回类型的函数并在一个声明语句中定义一个变量 |
禁止 |
CWG 1346 | C++11 | 带括号的表达式列表不能分配给 auto 变量 | 允许 |
CWG 1347 | C++11 | 使用 auto 说明符的声明可以定义两个变量 类型分别为 `T` 和 std::initializer_list<T> |
禁止 |
CWG 1852 | C++14 | auto 说明符在 decltype(auto) 中也是一个占位符 | 不是占位符 在这种情况下 |
CWG 1892 | C++11 | 函数指针类型-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