decltype(C++)

decltype 형식 지정자는 지정된 식의 형식을 생성합니다. decltype 형식 지정자는 키워드(keyword) 함께 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형식입니다. 매개 변수가 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입니다.

decltypeauto

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 형식 지정자를 사용하여 늦게 지정된 반환 형식을 선언합니다. 늦게 지정된 반환 형식은 선언이 코딩될 때가 아니라 컴파일될 때 결정됩니다.

다음 프로토타입에서는 대체 함수 선언의 구문을 보여 줍니다. constvolatile 한정자 및throw 예외 사양은 선택 사항입니다. function_body 자리 표시자는 함수가 수행하는 작업을 지정하는 복합 문을 나타냅니다. 가장 좋은 코딩 방법으로 문의 expression 자리 표시자는 문(decltype있는 function_body경우)에 지정된 return 식과 일치해야 합니다.

autofunction_name(parametersopt)constopt opt->)expressiondecltype(noexceptvolatile{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 이상이 필요합니다.