decltype 형식 지정자는 지정된 식의 형식을 생성합니다.
decltype 형식 지정자는 키워드와 함께auto 템플릿 라이브러리를 작성하는 개발자에게 주로 유용합니다.
decltype 반환 형식이 템플릿 인수의 형식에 따라 달라지는 함수 템플릿을 사용하고 auto 선언합니다. 또는 다른 함수에 대한 호출을 래핑한 다음 래핑된 함수의 반환 형식을 반환하는 함수 템플릿을 사용하고 autodecltype 선언합니다.
문법
decltype(expression)
매개 변수
expression
식입니다. 자세한 내용은 식을 참조하세요.
반환 값
매개 변수의 형식입니다 expression .
비고
decltype 형식 지정자는 Visual Studio 2010 이상 버전에서 지원되며 네이티브 또는 관리 코드와 함께 사용할 수 있습니다.
decltype(auto) (C++14)는 Visual Studio 2015 이상에서 지원됩니다.
컴파일러는 다음 규칙을 사용하여 매개 변수의 형식을 결정합니다 expression .
매개 변수가
expression식별자 또는 클래스 멤버 액세스인decltype(expression)expression경우 . 이러한 엔터티가 없거나 매개 변수 이름이expression오버로드된 함수 집합인 경우 컴파일러는 오류 메시지를 생성합니다.매개 변수가
expression함수 또는 오버로드된 연산자 함수에 대한 호출인decltype(expression)경우 함수의 반환 형식입니다. 오버로드된 연산자 주위의 괄호는 무시됩니다.매개 변수가
expressionrvaluedecltype(expression)이면 .의expression형식입니다. 매개 변수가expressionlvaluedecltype(expression)이면 형식에 대한 lvalue 참조expression입니다.
다음 코드 예제에서는 형식 지정자의 일부 사용을 decltype 보여 줍니다. 먼저 다음 문을 코딩한 것으로 가정합니다.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
다음으로, 다음 표의 4개 decltype 문에서 반환되는 형식을 검사합니다.
| 성명서 | 유형 | 비고 |
|---|---|---|
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에서는 후행 반환 형식의 형식 지정자를 키워드와 auto 함께 사용하여 decltype 해당 템플릿 인수의 형식에 따라 반환 형식이 종속된 함수 템플릿을 선언할 수 있습니다. 예를 들어 함수 템플릿의 반환 형식이 템플릿 인수의 형식에 따라 달라지는 다음 코드 예제를 고려해 보세요. 코드 예제 UNKNOWN 에서 자리 표시자는 반환 형식을 지정할 수 없다는 것을 나타냅니다.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; }
형식 지정자를 도입 decltype 하면 개발자가 함수 템플릿에서 반환하는 식의 형식을 가져올 수 있습니다. 나중에 표시되는 대체 함수 선언 구문 , auto 키워드 및 decltype 형식 지정자를 사용하여 늦게 지정된 반환 형식을 선언합니다. 늦게 지정된 반환 형식은 선언이 코딩될 때가 아니라 컴파일될 때 결정됩니다.
다음 프로토타입은 대체 함수 선언의 구문을 보여 줍니다.
const 및 volatile 한정자 및 throw예외 사양은 선택 사항입니다.
function_body 자리 표시자는 함수가 수행하는 작업을 지정하는 복합 문을 나타냅니다. 가장 좋은 코딩 방법으로 문의 expression 자리 표시자는 문(decltype있는 function_body경우)에 지정된 return 식과 일치해야 합니다.
auto
function_name
(
parameters
선택)const선택volatile선택->decltype(expression)noexcept선택{function_body};
다음 코드 예제에서 함수 템플릿의 myFunc 늦게 지정된 반환 형식은 및 템플릿 인수의 tu 형식에 따라 결정됩니다. 가장 좋은 코딩 사례로, 코드 예제에서는 완벽한 전달을 지원하는 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 이상이 필요합니다.