C++decltypeタイプの引数

8540 ワード

このシリーズの文章は@yhl_からなります.leo製品、転載は出所を明記してください.
記事のリンク:http://blog.csdn.net/yhl_leo/articale/detail/50865552
1基本文法decltypeタイプの引数は、指定された式のタイプを生成します.このプロセスでは、コンパイラは式を解析し、そのタイプを得るが、式の値は実際に計算されない.
構文:
decltype( expression )
コンパイラは、以下の規則を使用して、expressionパラメータの種類を決定する.
  • は、expressionパラメータが識別子またはクラスメンバーアクセスである場合、decltype(expression)expressionによって命名されたエンティティのタイプである.このようなエンティティが存在しない場合、またはexpressionパラメータのセットがリロード関数として命名されると、コンパイラはエラーメッセージを生成する.
  • は、expressionパラメータが、1つの関数または1つのリロード演算子関数に対する呼び出しである場合、decltype(expression)は、関数の返却タイプである.演算子の両側の括弧は無視されます.
  • は、expressionパラメータが右の値である場合、decltype(expression)expressionタイプである.expressionパラメータが左値である場合、decltype(expression)は左値参照タイプのexpressionである.
  • 以下のコードの例を示します.
    int var;
    const int&& fx(); 
    struct A { double x; }
    const A* a = new A();
    語句
    タイプ
    コメントdecltype(fx());const int && const intdecltype(var);int変数varのタイプdecltype(a->x);doubleメンバーアクセスのタイプdecltype((a->x));const double&内部括弧は、メンバーがアクセスして計算するのではなく、表現として文をもたらします.aは、constポインタであると宣言しているので、タイプはconst doubleへの参照である.
    2 decltypeと引用decltypeが使用する表現が変数でない場合、decltypeは式の結果に対応するタイプを返します.しかし、いくつかの表現は、1つの参照タイプをdecltypeに返します.一般的に、このような状況が発生した場合、この表式の結果オブジェクトは、1つの割当文の左の値として使用できることを意味する.
    // decltype          
    int i = 42, *p = &i, &r = i;
    decltype(r + 0) b; // OK,       int,  b   (    ) int
    decltype(*p) c; // Error, c int&,      
    rは1つの参照であるので、decltype(r)の結果は参照タイプであり、結果のタイプがrによって指定されるタイプであれば、rを表現の一部としてもよく、r+0のように、この表現の結果は1つの参照ではなく具体的な値になることは明らかである.
    一方、表式の内容が参照解除操作である場合、decltypeは参照タイプを得る.私たちがよく知っているように、参照解除ポインタは、ポインタが指すオブジェクトを得ることができ、また、このオブジェクトに値を割り当てることができるので、decltype(*p)の結果のタイプはint&であって、intではない.
    3 decltype及びauto
  • トップレベルのconstを処理する方法と、引用の仕方が異なる(参照:C+autタイプの引数)
  • decltypeが使用する表現が変数である場合、decltypeは、トップconstと参照を含む変数のタイプを返します.
    const int ci = 0, &cj = ci;
    decltype(ci) x = 0; // x    const int
    decltype(cj) y = x; // y    const int&,y     x
    decltype(cj) z; // Error, z     ,     
  • decltypeの結果のタイプは、表現形式と密接に関係している.decltypeで使用される参照に対して、変数名に括弧がセットされている場合、得られたタイプと括弧がない場合は異なる.decltypeが括弧を使わない変数を使用している場合、結果はその変数の種類です.変数に1つまたは複数の括弧を加えると、コンパイラは表現として扱われます.
    decltype((i)) d; // Error, d int&,      
    decltype(i) e;   // OK, e        int
  • テンプレート関数の返却タイプ
  • は、C+11において、戻りタイプに尾行されたdecltypeタイプの引数とautoキーワードを使用して、戻りタイプがそのテンプレートパラメータタイプに依存するテンプレート関数を宣言することができる.
  • は、C+14において、バックタイプのdecltype(auto)を有しないで返しタイプを宣言することができ、その戻りタイプはテンプレートパラメータタイプに依存するテンプレート関数である.
  • 例えば、求和テンプレート関数を定義します.
    //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); };
    
    (forward:パラメータが右または右の値で参照されている場合、条件付きでそのパラメータを右の値に強制的に変換する.)
    ソースコードの一部を添付します.
    #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
    参考資料:
  • Microsoft Developer Network:decltype(C+)
  • C++Primer(第五版)》Stnley B.Lippman.