5

次の小さな例は私の問題を示しています。

template<class T> struct X
{
    static void xxx(T& x) { }
    static void xxx(T&& x) { }
};

int main(int argc, char** argv)
{
    int x = 9;
    X<int>::xxx(x); // OK.
    X<int&>::xxx(x); // ERROR!
    return 0;
}

エラーメッセージ(GCC):

エラー:'static void X :: xxx(T &&)[with T = int&]'はオーバーロードできません
エラー:with' static void X :: xxx(T&)[with T = int&]'</ p>

なんで?T = int&---> inにT&置き換えられますか?int&&static void xxx(T& x)

質問に対する答えが「はい」の場合、次のようになります。

  • T&は左辺値参照ではなく、右辺値参照になります。
  • そして、次のコードが機能するはずです。

しかし、そうではありませんでした:

template<class T> struct X
{
    static void xxx(T& x) { }
};

int main(int argc, char** argv)
{
    X<int&>::xxx(2); // ERROR!
    return 0;
}

エラーメッセージ(GCC):

エラー:'X :: xxx(int)'の呼び出しに一致する関数がありません<br>注:候補は次のとおりです:static void X :: xxx(T&)[with T = int&]

その場合T&、withT = int&は等しくT&&なく、右辺値参照でもありません。しかし、そうでない場合、なぜ最初の例が機能しないのですか?(これは再帰的な問題です!)


しかし、同様の問題はポインター型では発生しませんでした。

#include <iostream>

template<class T> struct X
{
    static void xxx(T* x) { std::cout << **x << std::endl; }
};

int main(int argc, char** argv)
{
    int x = 10;
    int* xx = &x;
    X<int*>::xxx(&xx); // OK. call X<int*>::xxx(int**)
    return 0;
}

この動作で参照が異なるのはなぜですか?

4

1 に答える 1

10

C ++ 11言語標準には、これが§8.3.2[dcl.ref] / 6(読みやすくするために再フォーマットされた)でどのように機能するかについての説明があります。

typedef、type template-parameter、またはdecltype-specificerTRが、型への参照である型を示すT場合、

  • タイプ「 lvaluereferencetocv 」を作成しようとすると、タイプ「lvaluereferenceto TR」が作成されますT
  • タイプ「rvaluereferencetocv」を作成しようとすると、タイプが作成されますTRTR

あなたの例を考えてみましょう(上記の言語と一致するように名前を変更しました)TTR

template<class TR> struct X
{
    static void xxx(TR& x)  { }
    static void xxx(TR&& x) { }
};

(so、)でインスタンス化しようとするXと、のインスタンス化は次のようになります。TR = int&T = intxxx

static void xxx(TR& x)  { }   -->   static void xxx(int& x) { }
static void xxx(TR&& x) { }   -->   static void xxx(int& x) { }

最初のケースでは、「への左辺値参照」を作成しようとします。これは「へのTR左辺値参照」になりTます。 Tint、なので、パラメータタイプは。になりint&ます。

2番目のケースでは、「への右辺値参照」を作成しようとします。これは、にTRなります。TRint&

パラメータタイプは両方のオーバーロードで同じであるため、エラーが発生します。

于 2010-08-22T17:51:15.600 に答える