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 - (C++20부터) concept 이름(선택적으로 한정됨), 선택적으로 <> 로 둘러싸인 템플릿 인수 목록이 뒤따를 수 있음
1) 타입은 template argument deduction 규칙을 사용하여 추론됩니다.
2) 타입은 decltype(expr) 입니다. 여기서 expr 은 초기화자 또는 return 문 에서 사용된 피연산자입니다.

플레이스홀더 auto const 또는 & 와 같은 한정자와 함께 사용될 수 있으며, 이러한 한정자들은 타입 추론에 참여합니다. 플레이스홀더 decltype ( auto ) 는 선언된 타입의 유일한 구성 요소여야 합니다. (C++14부터)

type-constraint 이 존재하는 경우, 플레이스홀더에 대해 추론된 타입을 T 라고 하면, type-constraint 는 다음과 같이 constraint expression 을 도입합니다:

  • type-constraint Concept<A 1 , ..., A n > 인 경우, constraint expression은 Concept<T, A 1 , ..., A n > 입니다;
  • 그렇지 않은 경우 ( type-constraint 이 인수 목록 없이 Concept 인 경우), constraint expression은 Concept<T> 입니다.

Constraint expression이 유효하지 않거나 false 를 반환하는 경우 추론이 실패합니다.

(since C++20)

설명

자리 표시자 타입 지정자는 다음의 맥락에서 나타날 수 있습니다:

매개변수 선언

다음 매개변수 선언에서 선언된 매개변수의 타입은 다음 구문 (1) 일 수 있습니다:

  • lambda expression 의 매개변수가 placeholder type을 가지면, 해당 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의 반환 타입은 정의될 때 추론됨

변수 선언

플레이스홀더 타입을 사용하여 선언된 변수의 타입은 해당 변수의 초기화자 로부터 추론됩니다. 이러한 사용은 변수의 초기화 선언에서 허용됩니다.

플레이스홀더 타입은 선언 지정자 시퀀스 내의 선언 지정자 중 하나로만 나타나거나, 또는 후행 반환 타입에서 해당 선언 지정자를 대체하는 타입을 지정하는 타입 지정자 중 하나로만 나타날 수 있습니다. 이 경우, 선언은 적어도 하나의 변수를 선언해야 하며, 각 변수는 비어 있지 않은 초기화자를 가져야 합니다.

// 선언 지정자에서의 "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 표현식

플레이스홀더 타입은 new 표현식 의 타입-id에 있는 타입 지정자 시퀀스에서 사용될 수 있습니다. 이러한 타입-id에서 플레이스홀더 타입은 타입 지정자 시퀀스 내의 타입 지정자 중 하나로 나타나거나, 그러한 타입 지정자를 대체하는 타입을 지정하는 후행 반환 타입으로 나타나야 합니다.

함수 스타일 캐스트

auto 타입 지정자는 함수 스타일 캐스트 의 타입 지정자로 사용될 수 있습니다.

(C++23부터)

참고 사항

C++11 이전까지, auto 저장 기간 지정자 의 의미론을 가지고 있었습니다.

위에서 명시적으로 언급되지 않은 컨텍스트에서 플레이스홀더 타입을 사용하는 프로그램은 잘못된 형식입니다.

선언이 여러 개체를 선언하고, 선언 지정자 시퀀스가 플레이스홀더 타입을 사용하는 경우, 다음 조건 중 하나라도 충족되면 프로그램은 형식에 맞지 않습니다:

  • 선언된 엔티티 중 일부는 변수가 아닙니다.
  • 플레이스홀더 타입을 대체하는 타입이 각 추론에서 동일하지 않습니다.
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;// 정상
};

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 << "c2를 통한 수정 전, a = " << a << '\n';
    ++c2;
    std::cout << "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); // "사용되지 않은 변수" 경고를 억제합니다
}

가능한 출력:

c2를 통한 수정 전, a = 3
 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 decltype ( auto ) auto 지정자도 플레이스홀더였음 이 경우에는
플레이스홀더가 아님
CWG 1892 C++11 함수 포인터 타입 ID의 반환 타입이 auto 일 수 있었음 금지됨
CWG 2476 C++11 CWG 이슈 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 Placeholder type specifiers [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]