decltype
(C++)
decltype
형식 지정자는 지정된 식의 형식을 생성합니다. decltype
형식 지정자는 키워드(keyword) 함께 auto
템플릿 라이브러리를 작성하는 개발자에게 주로 유용합니다. decltype
반환 형식이 템플릿 인수의 형식에 따라 달라지는 함수 템플릿을 사용하고 auto
선언합니다. 또는 다른 함수에 대한 호출을 래핑한 다음 래핑된 함수의 반환 형식을 반환하는 함수 템플릿을 사용하고 auto
decltype
선언합니다.
구문
decltype(
expression
)
매개 변수
expression
식입니다. 자세한 내용은 식을 참조하세요.
반환 값
expression
매개 변수의 형식입니다.
설명
decltype
형식 지정자는 Visual Studio 2010 이상 버전에서 지원되며 네이티브 또는 관리 코드와 함께 사용할 수 있습니다. decltype(auto)
(C++14)는 Visual Studio 2015 이상에서 지원됩니다.
컴파일러는 다음 규칙을 사용하여 매개 변수의 형식을 결정합니다 expression
.
매개 변수가
expression
식별자 또는 클래스 멤버 액세스인decltype(expression)
expression
경우 . 이러한 엔터티가 없거나 매개 변수 이름이expression
오버로드된 함수 집합인 경우 컴파일러는 오류 메시지를 생성합니다.매개 변수가
expression
함수 또는 오버로드된 연산자 함수에 대한 호출인decltype(expression)
경우 함수의 반환 형식입니다. 오버로드된 연산자를 묶는 괄호는 무시됩니다.매개 변수가
expression
rvaluedecltype(expression)
이면 .의expression
형식입니다. 매개 변수가expression
lvaluedecltype(expression)
이면 형식에 대한 lvalue 참조expression
입니다.
다음 코드 예제에서는 형식 지정자의 일부 사용을 decltype
보여 줍니다. 먼저 다음 문을 코딩한 것으로 가정합니다.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
다음으로, 다음 표의 4개 decltype
문에서 반환되는 형식을 검사합니다.
문 | Type | 주의 |
---|---|---|
decltype(fx()); |
const int&& |
에 대한 rvalue 참조 입니다 const int . |
decltype(var); |
int |
var 변수의 형식입니다. |
decltype(a->x); |
double |
멤버 액세스의 형식입니다. |
decltype((a->x)); |
const double& |
내부 괄호를 사용하면 문이 멤버 액세스가 아니라 식으로 평가됩니다. 포인터로 const 선언되기 때문에 a 형식은 .에 대한 참조const double 입니다. |
decltype
및 auto
C++14에서는 후행 반환 형식 없이 사용하여 decltype(auto)
해당 템플릿 인수의 형식에 따라 반환 형식이 종속된 함수 템플릿을 선언할 수 있습니다.
C++11에서는 키워드(keyword) 함께 auto
후행 반환 형식의 형식 지정자를 사용하여 decltype
해당 템플릿 인수의 형식에 따라 반환 형식이 종속된 함수 템플릿을 선언할 수 있습니다. 예를 들어 함수 템플릿의 반환 형식이 템플릿 인수의 형식에 따라 달라지는 다음 코드 예제를 고려해 보세요. 코드 예제 UNKNOWN
에서 자리 표시자는 반환 형식을 지정할 수 없다는 것을 나타냅니다.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
형식 지정자를 도입 decltype
하면 개발자가 함수 템플릿에서 반환하는 식의 형식을 가져올 수 있습니다. 나중에 표시되는 대체 함수 선언 구문, auto
키워드(keyword) 및 decltype
형식 지정자를 사용하여 늦게 지정된 반환 형식을 선언합니다. 늦게 지정된 반환 형식은 선언이 코딩될 때가 아니라 컴파일될 때 결정됩니다.
다음 프로토타입에서는 대체 함수 선언의 구문을 보여 줍니다. const
및 volatile
한정자 및throw
예외 사양은 선택 사항입니다. function_body
자리 표시자는 함수가 수행하는 작업을 지정하는 복합 문을 나타냅니다. 가장 좋은 코딩 방법으로 문의 expression
자리 표시자는 문(decltype
있는 function_body
경우)에 지정된 return
식과 일치해야 합니다.
auto
function_name
(
parameters
opt)
const
opt opt->
)
expression
decltype(
noexcept
volatile
{
function_body
};
다음 코드 예제에서 함수 템플릿의 myFunc
늦게 지정된 반환 형식은 및 템플릿 인수의 t
u
형식에 따라 결정됩니다. 가장 좋은 코딩 사례로, 코드 예제에서는 완벽한 전달을 지원하는 rvalue 참조 및 forward
함수 템플릿도 사용합니다. 자세한 내용은 Rvalue 참조 선언자(&R)를 참조하세요.
//C++11
template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
{ return forward<T>(t) + forward<U>(u); };
//C++14
template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
{ return forward<T>(t) + forward<U>(u); };
decltype
및 전달 함수(C++11)
전달 함수는 다른 함수에 대한 호출을 래핑합니다. 해당 인수 또는 이러한 인수를 포함하는 식의 결과를 다른 함수로 전달하는 함수 템플릿을 고려해 보십시오. 또한 전달 함수는 다른 함수를 호출한 결과를 반환합니다. 이 시나리오에서 전달 함수의 반환 형식은 래핑된 함수의 반환 형식과 동일해야 합니다.
이 시나리오에서는 형식 지정자가 없으면 적절한 형식 식을 작성할 decltype
수 없습니다. decltype
형식 지정자는 함수가 참조 형식을 반환하는지 여부에 대한 필수 정보를 잃지 않으므로 제네릭 전달 함수를 사용하도록 설정합니다. 전달 함수의 코드 예제는 이전 myFunc
함수 템플릿 예제를 참조하세요.
예제
다음 코드 예제에서는 함수 템플릿 Plus()
의 늦게 지정된 반환 형식을 선언합니다. 함수는 Plus
오버로드를 사용하여 두 피연산자를 operator+
처리합니다. 따라서 함수의 더하기 연산자(+
) 및 반환 형식의 Plus
해석은 함수 인수의 형식에 따라 달라집니다.
// decltype_1.cpp
// compile with: cl /EHsc decltype_1.cpp
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
using namespace std;
template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
decltype(forward<T1>(t1) + forward<T2>(t2))
{
return forward<T1>(t1) + forward<T2>(t2);
}
class X
{
friend X operator+(const X& x1, const X& x2)
{
return X(x1.m_data + x2.m_data);
}
public:
X(int data) : m_data(data) {}
int Dump() const { return m_data;}
private:
int m_data;
};
int main()
{
// Integer
int i = 4;
cout <<
"Plus(i, 9) = " <<
Plus(i, 9) << endl;
// Floating point
float dx = 4.0;
float dy = 9.5;
cout <<
setprecision(3) <<
"Plus(dx, dy) = " <<
Plus(dx, dy) << endl;
// String
string hello = "Hello, ";
string world = "world!";
cout << Plus(hello, world) << endl;
// Custom type
X x1(20);
X x2(22);
X x3 = Plus(x1, x2);
cout <<
"x3.Dump() = " <<
x3.Dump() << endl;
}
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42
Visual Studio 2017 이상: 템플릿이 인스턴스화되지 않고 선언될 때 컴파일러는 인수를 구문 분석 decltype
합니다. 따라서 인수에 decltype
종속되지 않는 특수화가 발견되면 인스턴스화 시간으로 지연되지 않습니다. 즉시 처리되고 그 때 발생하는 모든 오류가 진단됩니다.
다음 예제에서는 선언 시점에 발생한 컴파일러 오류를 보여 줍니다.
#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
struct BadType {};
template <class U>
static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
template <class U>
static BadType Test(...);
static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;
};
constexpr bool test1 = IsCallable<int(), int>::value;
static_assert(test1, "PASS1");
constexpr bool test2 = !IsCallable<int*, int>::value;
static_assert(test2, "PASS2");
요구 사항
Visual Studio 2010 이상 버전.
decltype(auto)
에는 Visual Studio 2015 이상이 필요합니다.
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기