名前空間
変種
操作

プレースホルダー型指定子 (C++11以降)

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

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

目次

[編集] 構文

型制約 (オプション) auto (1)
型制約 (オプション) decltype(auto) (2) (C++14以降)
type-constraint - (C++20以降) コンセプト名、オプションで修飾子付き、オプションで<>で囲まれたテンプレート引数リストが続く
1) 型はテンプレート引数推論の規則を使用して推論されます。
2) 型はdecltype(expr)であり、exprは初期化子またはreturn文で使用されるものです。

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

型制約が存在する場合、プレースホルダーに推論された型をTとすると、型制約は次のように制約式を導入します。

  • 型制約Concept<A1, ..., An>の場合、制約式はConcept<T, A1, ..., An>です。
  • それ以外の場合(型制約が引数リストのないConceptの場合)、制約式はConcept<T>です。

制約式が無効であるか、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

[編集] 変数宣言

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

プレースホルダー型は、宣言指定子シーケンスの宣言指定子の1つとして、またはそのような宣言指定子を置き換える型を指定する末尾戻り値型の型指定子の1つとしてのみ現れることができます。この場合、宣言は少なくとも1つの変数を宣言する必要があり、各変数には空でない初期化子が必要です。

// “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では、プレースホルダー型は、型指定子シーケンスの型指定子の1つとして、またはそのような型指定子を置き換える型を指定する末尾戻り値型として現れる必要があります。

関数形式キャスト

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::形式の入れ子になった名前指定子は、制約付き型プレースホルダー推論の規則に従って、クラス型または列挙型に置き換えられるプレースホルダーです。

(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; } // 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指定子は、末尾戻り値型を持つ関数を宣言し、
1つの宣言文で変数を定義するために使用できる
禁止された
CWG 1346 C++11 括弧で囲まれた式リストは、auto変数に割り当てることができなかった 許可
CWG 1347 C++11 auto指定子を含む宣言は、2つの変数を
それぞれ型Tstd::initializer_list<T>で定義できた
禁止された
CWG 1852 C++14 decltype(auto)auto指定子もプレースホルダーであった プレースホルダーではない
この場合に
CWG 1892 C++11 関数ポインタのtype-idの戻り値型はautoであった 禁止された
CWG 2476 C++11 CWG issue 1892の解決により、初期化子からの
関数ポインタ変数の戻り値型の推論が禁止された
許可

[編集] 参照

  • C++23標準 (ISO/IEC 14882:2024)
  • 9.2.9.6 プレースホルダー型指定子 [dcl.spec.auto]
  • C++20 standard (ISO/IEC 14882:2020)
  • 9.2.8.5 プレースホルダー型指定子 [dcl.spec.auto]
  • C++17 standard (ISO/IEC 14882:2017)
  • 10.1.7.4 auto指定子 [dcl.spec.auto]
  • C++14 standard (ISO/IEC 14882:2014)
  • 7.1.6.4 auto指定子 [dcl.spec.auto]
  • C++11 standard (ISO/IEC 14882:2011)
  • 7.1.6.4 auto指定子 [dcl.spec.auto]
English 日本語 中文(简体) 中文(繁體)