Decltype (C++) (declare type)

C++ 2019. 12. 25. 10:06
반응형
 

decltype (C++)

decltype (C++) In this article --> The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to

docs.microsoft.com

decltype 유형 지정자는 지정된 표현식의 유형을 산출합니다. decltype 유형 지정자는 auto 키워드와 함께 주로 템플리트 라이브러리를 작성하는 개발자에게 유용합니다. auto  decltype을 사용하여 반환 형식이 해당 템플릿 인수의 형식에 따라 달라지는 템플릿 함수를 선언합니다. 또는 auto  decltype을 사용하여 호출을 다른 함수로 감싼 템플릿 함수를 선언한 다음 감싼 함수의 반환 유형을 반환합니다.

 

 

 

 

구문

1
decltype( exp 식 )
 

매개변수

매개변수 설명
exp 식 exp 식의 더 많은 정보를 알고 싶으면, exp 식을 확인하세요.

 

 

 

반환값

exp 식 매개 변수의 유형입니다.

 

 

 

 

 

참고

decltype 형식 지정자는 Visual Studio 2010 또는 이후 버전에서 지원되며 네이티브 또는 관리되는 코드와 함께 사용할 수 있습니다. decltype(auto) (C ++ 14)은 Visual Studio 2015 이상에서 지원됩니다.

 

컴파일러는 다음 규칙을 사용하여 표현식의 매개 변수의 유형을 결정합니다.

 

  • exp 식 매개 변수가 식별자 또는 클래스 멤버 액세스를 하는 경우, decltype(exp 식)은 exp 식에 의해 명명된 엔터티의 유형입니다. 그러한 엔티티가 없거나 exp 식 매개 변수가 오버로드 된 함수 세트의 이름을 지정하면 컴파일러는 오류 메시지를 생성합니다.
  • exp 식 매개 변수가 함수 또는 오버로드 된 연산자 함수에 대한 호출이면 decltype(exp 식)은 함수의 반환 유형입니다. 오버로드 된 연산자 주위의 괄호는 무시됩니다.
  • exp 식 매개 변수가 rvalue 인 경우 decltype (exp 식)은 exp 식의 유형입니다.
    exp 식 매개 변수가 lvalue 인 경우 decltype (exp 식)은 exp 식 유형에 대한 lvalue 참조입니다.

 

다음 코드 예제에서는 decltype 형식 지정자를 일부 사용하는 방법을 보여줍니다. 먼저 다음 문장을 코딩했다고 가정합니다.

1
2
3
4
int var;
const int&& fx();
struct A { double x; }
const A* a = new A();
 

 

 

다음 표의 네 가지 decltype 문에서 반환하는 형식을 확인합니다.

구문 설명
decltype(fx()); const int&& const int의 rvalue 참조
decltype(var); int var 의 변수형
decltype(a->x); double 멤버 액세스 유형
decltype((a->x)); const double& 내부 괄호로 인해 명령문은 멤버 액세스 대신 (exp 식)으로 평가됩니다. 그리고 a는 const 포인터로 선언되기 때문에,이 타입은 const double에 대한 참조입니다.

 

 

 

Decltype 과 Auto

 

C ++ 14에서는 반환 형식이 템플릿 인수의 형식에 따라 달라지는 템플릿 함수를 선언하기 위해 후행 반환 형식이없는 decltype (auto)을 사용할 수 있습니다.

 

C ++ 11에서는 auto 키워드와 함께 [후행 반환 형식 - trailing return type] decltype 형식 지정자를 사용하여 반환 형식이 해당 템플릿 인수의 형식에 따라 달라지는 템플릿 함수를 선언할 수 있습니다. 예를 들어 템플릿 함수의 반환 형식이 템플릿 인수의 형식에 따라 달라지는 다음 코드 예제를 고려해보십시오. 코드 예제에서 UNKNOWN 자리 표시자는 반환 형식을 지정할 수 없음을 나타냅니다.

1
2
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
 

decltype 타입 지정자의 도입으로 개발자는 템플릿 함수가 반환하는 표현식의 유형을 얻을 수 있습니다. 나중에 표시되는 대체 함수 선언 구문, auto 키워드 및 decltype 유형 지정자를 사용하여 [후지정 - late-specified] 반환 유형을 선언하십시오. [후지정 - late-specified] 반환 유형은 선언이 코드가 작성 될 때가 아닌 컴파일 될 때 결정됩니다.

 

다음 프로토 타입은 대체 함수 선언의 구문을 보여줍니다. const  volatile 한정자 및 throw 예외 지정은 선택 사항(Option)입니다. function_body 자리 표시자는 함수가 수행하는 작업을 지정하는 복합 명령문을 나타냅니다. 최상의 코딩 방법으로, decltype 문의 exp 식 자리 표시자는 function_body에서 return 문이 지정한 표현식과 일치해야 합니다.

 

auto 함수이름 ( 매개변수 (opt) ) const (opt) volatile (opt) -> decltype( exp 식 ) throw (opt) 함수 내용 };

 

다음 코드 예제에서 myFunc 템플릿 함수의 후지정된 반환 유형은 t 및 u 템플릿 인수의 유형에 따라 결정됩니다. 최상의 코딩 방법으로, 코드 예제에서는 완전 전달_perfect forwarding을 지원하는 rvalue 참조와 forward 함수 템플릿도 사용합니다. 자세한 내용은 Rvalue 참조 선언자: &&를 참조하십시오.

1
2
3
4
5
6
7
8
9
10
//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); };
 

 

 

이 단락의 핵심 설명이 모두 들어있는 예제이다.

 

1번줄부터 시작되는 C++11 버전에서의 코드는_

auto myFunc(T&& t, U&& u) 의 auto를 정상적으로 반환하기 위해서 추론이 필요한데 그것을 함수 선언부 뒤쪽에 나열한다는 뜻이다.

그것은 -> decltype (forward<T>(t) + forward<U>(u)) 식으로 표현이 되며, 이를 본문에서는 [후행 반환 형식 -trailing return type]이라 일컬었다.

 

그리고 C++14 이후에서는_ -> VS 2015 이후

해당 후행 코드들이 필요없는 것을 보여준다. 단, 반환자 auto에 decltype을 감싸 [decltype(auto)] 형태로 표현해주어야 한다는 점을 시사한다.

 

 

 

 

+Forward decalration -> 전방 선언

+Forward function -> 전방 함수

 

+Forwarding function -> 함수 전달자

+Perfect Forwarding -> 완전 전달자

 

 

 

Decltype 와 Forwarding(전달) 함수 (C++11)

전달 함수는 다른 함수의 호출들을 감쌉니다. 인수를 전달하는 함수 템플릿 또는 해당 인수와 관련된 표현식의 결과를 다른 함수로 전달한다고 가정하십시오. 또한 전달 함수는 다른 함수를 호출한 결과를 반환합니다. 이 시나리오에서 전달 함수의 return 유형은 감싼 함수의 리턴 유형과 동일해야합니다.

 

이 예상도에서는 decltype 형식 지정자 없이 적절한 표현식을 작성할 수 없습니다. decltype 형식 지정자는 함수가 참조 형식을 반환하는지 여부에 대한 필수 정보를 잃지 않으므로 일반 전달 기능을 사용 가능하게합니다. 전달 함수의 코드 예제는 이전 myFunc 템플릿 함수 예제를 참조하십시오.

 

 

 

 

예제

다음 코드 예제에서는 후지정(late-specified) 템플릿 함수 Plus()의 반환 형식을 선언합니다. Plus 함수는 operator+ 오버로딩으로 두 개의 피연산자를 처리합니다. 따라서 더하기 연산자 (+)의 해석과 Plus 함수의 반환 형식은 함수 인수의 형식에 따라 다릅니다.

 

예제_

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 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;
}
 
 

 

출력_

1
2
3
4
Plus(i, 9= 13
Plus(dx, dy) = 13.5
Hello, world!
 

 

 

 

예제

Visual Studio 2017 이후: 컴파일러는 템플릿이 인스턴스화되기 보다는 선언 될 때 decltype 인수들을 분석합니다. 결과적으로, 의존적이지 않은 특수화(specialized)가 decltype 인수에서 발견되면 인스턴스화 시간으로 연기되지 않고 즉시 처리되고 결과 오류는 그 시점에 진단됩니다.

 

다음 예제에서는 선언 지점에서 발생하는 컴파일러 오류를 보여줍니다.

 

 

예제_

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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");
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

*perfect forwading 완전 전달자 - RValue, LValue

반응형

'C++' 카테고리의 다른 글

Mutable, Auto  (0) 2019.12.25
volatile  (0) 2019.12.25
저장소 클래스 - Storage classes (static, extern, thread_local, register)  (0) 2019.12.25
Timer - 시간 측정기  (0) 2019.12.25
const*, constexpr**  (0) 2019.12.25
Posted by Kestone Black Box
,