Namespaces
Variants

Placeholder type specifiers (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const / volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

プレースホルダー型指定子は、後に置き換えられる プレースホルダー型 を指定します。通常は 初期化子 からの推論によって置き換えられます。

目次

構文

type-constraint  (オプション) auto (1)
type-constraint  (オプション) decltype(auto) (2) (C++14以降)
type-constraint - (since C++20) オプションで修飾された concept 名、その後にオプションで <> で囲まれたテンプレート引数リストが続くもの
1) 型は template argument deduction のルールを使用して推論されます。
2) 型は decltype(expr) であり、ここで expr は初期化子または return文 で使用されるオペランドです。

プレースホルダー auto は、 const & などの修飾子を伴うことができ、これらは型推論に参加します。 プレースホルダー decltype ( auto ) は宣言された型の唯一の構成要素でなければなりません。 (C++14以降)

type-constraint が存在する場合、 T をプレースホルダに対して推論された型とすると、 type-constraint は以下のように 制約式 を導入します:

  • type-constraint Concept<A 1 , ..., A n > の場合、制約式は Concept<T, A 1 , ..., A n > です;
  • それ以外の場合( type-constraint が引数リストなしの Concept である場合)、制約式は Concept<T> です。

制約式が無効であるか、 false を返す場合、推論は失敗します。

(C++20以降)

説明

プレースホルダ型指定子は以下の文脈で現れる可能性があります:

パラメータ宣言

以下のパラメータ宣言において、宣言されるパラメータの型は構文 (1) の形式をとることができます:

  • lambda expression のパラメータがプレースホルダ型を持つ場合、そのlambda expressionはgeneric lambdaとなります。
(C++14以降)
(C++17以降)
(C++20以降)

関数宣言

プレースホルダ型は、 宣言指定子 内で、 関数宣言子 の末尾戻り値型を含むものに現れることができます。

プレースホルダ型は、関数宣言子の宣言された戻り値型の宣言指定子または 型指定子 に現れることができます。 この場合、 戻り値型の推論 が適用されます。

(C++14以降)
auto f() -> int; // OK: fはintを返す
auto g() { return 0.0; } // C++14以降OK: gはdoubleを返す
auto h(); // C++14以降OK: hの戻り値型は定義時に推論される

変数宣言

プレースホルダー型を使用して宣言された変数の型は、その 初期化子 から推論されます。この使用法は変数の初期化宣言で許可されています。

プレースホルダ型は、宣言指定子シーケンス内の declaration specifiers の1つとして、またはそのような宣言指定子を置き換える型を指定する後置戻り値型の型指定子の1つとしてのみ現れます。この場合、宣言は少なくとも1つの変数を宣言しなければならず、各変数は空でない初期化子を持たなければなりません。

// 宣言指定子における「auto」
auto x = 5; // OK: x の型は int
const auto *v = &x, u = 6; // OK: v の型は const int*、u の型は const int
static auto y = 0.0; // OK: y の型は double
auto f() -> int;
auto (*fp)() -> auto = f; // OK: 後置戻り値型の「auto」は
                          // f から推論可能

構造化束縛宣言

auto 指定子は 構造化束縛 宣言で使用できます。

(C++17以降)

new expressions

プレースホルダ型は、 new式 の型IDの型指定子シーケンスで使用できます。このような型IDでは、プレースホルダ型は型指定子シーケンス内の型指定子の1つとして、またはそのような型指定子を置き換える型を指定する後置戻り値型として現れなければなりません。

関数形式キャスト

auto 型指定子は、 関数形式キャスト の型指定子として使用できます。

(C++23以降)

注記

C++11まで、 auto storage duration specifier の意味を持っていました。

上記で明示的に述べられていない文脈でプレースホルダ型を使用するプログラムは不適格です。

宣言が複数のエンティティを宣言し、かつ宣言指定子シーケンスがプレースホルダ型を使用する場合、以下のいずれかの条件が満たされるとプログラムは不適格となります:

  • 宣言されているエンティティの一部は変数ではありません。
  • プレースホルダー型を置き換える型が各推論で同一ではありません。
auto f() -> int, i = 0; // エラー: 「auto」で関数と変数を宣言している
auto a = 5, b = {1, 2}; // エラー: 「auto」の型が異なる

置換されていないプレースホルダー型を持つ関数または変数が式によって参照される場合、プログラムは不適格です。

auto v = 1;
auto l = [&]
{
    v++;
    return l;// エラー: lのプレースホルダ型が置換されていません
};
std::function<void()> p = [&]
{
    v++;
    return p;// OK
};

auto キーワードは、ネストされた名前指定子でも使用できます。 auto :: の形式のネストされた名前指定子は、プレースホルダーであり、 制約付き型 プレースホルダー推論の規則に従ってクラス型または列挙型に置き換えられます。

(concepts TS)
機能テストマクロ 規格 機能
__cpp_decltype_auto 201304L (C++14) decltype ( auto )

キーワード

auto , decltype

#include <iostream>
#include <utility>
template<class T, class U>
auto add(T t, U u) { return t + u; } // 戻り値の型は operator+(T, U) の型
// 関数呼び出しの完全転送は参照を返す可能性があるため decltype(auto) を使用する必要がある
template<class F, class... Args>
decltype(auto) PerfectForward(F fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}
template<auto n> // C++17 auto パラメータ宣言
auto f() -> std::pair<decltype(n), decltype(n)> // auto は波括弧初期化リストから推論できない
{
    return {n, n};
}
int main()
{
    auto a = 1 + 2;          // a の型は int
    auto b = add(1, 1.2);    // b の型は double
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), double>);
    auto c0 = a;             // c0 の型は int、a のコピーを保持
    decltype(auto) c1 = a;   // c1 の型は int、a のコピーを保持
    decltype(auto) c2 = (a); // c2 の型は int&、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>(); // 構造化束縛宣言
    auto d = {1, 2}; // OK: d の型は std::initializer_list<int>
    auto n = {5};    // OK: n の型は std::initializer_list<int>
//  auto e{1, 2};    // DR n3922 以降エラー、以前は std::initializer_list<int>
    auto m{5};       // OK: DR n3922 以降 m の型は int、以前は initializer_list<int>
//  decltype(auto) z = { 1, 2 } // エラー: {1, 2} は式ではない
    // auto はラムダ式の型など無名の型によく使用される
    auto lambda = [](int x) { return x + 3; };
//  auto int x; // C++98 では有効、C++11 以降エラー
//  auto x;     // C では有効、C++ ではエラー
    [](...){}(c0, c1, v, w, d, n, m, lambda); // 「未使用変数」警告を抑制
}

出力例:

before modification through c2, a = 3
 after modification through c2, a = 4

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 1265 C++11 auto 指定子を使用して、戻り値型を後置する関数の宣言と変数の定義を
1つの宣言文で行うことができた
禁止
CWG 1346 C++11 括弧付きの式リストを auto 変数に代入できなかった 許可
CWG 1347 C++11 auto 指定子を使用した宣言で、型がそれぞれ T std:: initializer_list < T > の2つの変数を
定義できた
禁止
CWG 1852 C++14 decltype ( auto ) 内の auto 指定子もプレースホルダーであった この場合はプレースホルダーではない
CWG 1892 C++11 関数ポインタ型IDの戻り値型を auto とすることができた 禁止
CWG 2476 C++11 CWG issue 1892 の解決により、関数ポインタ変数の
戻り値型の初期化子からの推論が禁止された
許可
N3922 C++11 auto の直接リスト初期化は std::initializer_list を推論する 複数要素の場合は不適格、
単一要素の場合は要素型を推論

参考文献

  • 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]
  • C++14 標準 (ISO/IEC 14882:2014):
  • 7.1.6.4 auto 指定子 [dcl.spec.auto]
  • C++11標準 (ISO/IEC 14882:2011):
  • 7.1.6.4 auto 指定子 [dcl.spec.auto]