Placeholder type specifiers (since C++11)
플레이스홀더 타입 지정자는 나중에, 일반적으로 초기화자 에서의 추론에 의해 대체될 플레이스홀더 타입 을 지정합니다.
목차 |
구문
type-constraint
(선택사항)
auto
|
(1) | ||||||||
type-constraint
(선택사항)
decltype(auto)
|
(2) | (C++14부터) | |||||||
| type-constraint | - |
(C++20부터)
concept
이름(선택적으로 한정됨), 선택적으로
<>
로 둘러싸인 템플릿 인수 목록이 뒤따를 수 있음
|
플레이스홀더
auto
는
const
또는
&
와 같은 한정자와 함께 사용될 수 있으며, 이러한 한정자들은 타입 추론에 참여합니다.
플레이스홀더
decltype
(
auto
)
는 선언된 타입의 유일한 구성 요소여야 합니다.
(C++14부터)
|
type-constraint
이 존재하는 경우, 플레이스홀더에 대해 추론된 타입을
Constraint expression이 유효하지 않거나 false 를 반환하는 경우 추론이 실패합니다. |
(since C++20) |
설명
자리 표시자 타입 지정자는 다음의 맥락에서 나타날 수 있습니다:
매개변수 선언다음 매개변수 선언에서 선언된 매개변수의 타입은 다음 구문 (1) 일 수 있습니다:
|
(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 ) |
키워드
예제
#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]
-
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