3

C++11 の完全な転送機能を試しています。Gnu g++ コンパイラは、関数とパラメーターのバインドのあいまいさの問題を報告します (エラーは、以下のソース コードの後に​​表示されます)。私の質問は、なぜそうなのかということです。関数とパラメーターのバインディングプロセスに従っていると、あいまいさがわかりません。私の推論は次のとおりです。 aは左辺値であるため、 main() でtf(a)を呼び出すとtf(int&) にバインドされます。次に、関数tfは左辺値参照int& aを関数gに転送するため、関数void g(int &a)を一意に呼び出す必要があります。したがって、あいまいさの理由がわかりません。オーバーロードされた関数g(int a)コードから削除されます。g(int a)はint &aとのバインドの候補にならないため、これは奇妙です。

これが私のコードです:

void g(int &&a)
{
  a+=30;
}

void g(int &a)
{
  a+=10;
}

void g(int a)   //existence of this function originates the ambiguity issue
{
  a+=20;
}

template<typename T>
void tf(T&& a)
{
  g(forward<T>(a));;
}

int main()
{
  int a=5;
  tf(a);
  cout<<a<<endl;
}

コンパイルg++ -std=c++11 perfectForwarding.cppは、次のエラーを報告します。

perfectForwarding.cpp: In instantiation of ‘void tf(T&&) [with T = int&]’:
perfectForwarding.cpp:35:7:   required from here
perfectForwarding.cpp:24:3: error: call of overloaded ‘g(int&)’ is ambiguous
perfectForwarding.cpp:24:3: note: candidates are:
perfectForwarding.cpp:6:6: note: void g(int&&) <near match>
perfectForwarding.cpp:6:6: note:   no known conversion for argument 1 from ‘int’ to ‘int&&’
perfectForwarding.cpp:11:6: note: void g(int&)
perfectForwarding.cpp:16:6: note: void g(int)
4

2 に答える 2

7

g(int a)はint &aとのバインドの候補にならないため、これは奇妙です。

それは真実ではない。g(int&)オーバーロードを削除するg(int)と、呼び出されます。両方が宣言されている場合、どちらも実行可能な候補であり、変換を必要としないため、あいまいです。

于 2013-09-18T19:32:11.130 に答える
4

Jonathan Wakely回答に追加します。

まず第一に、この問題は完全な転送とは何の関係もなくtf、写真から取り除くことができます.

とりあえず、次のコードだけを考えてみましょう:

void g(int) {}

int main() {
    int a = 5;       // a is an lvalue
    g(a);            // ok
    g(std::move(a)); // std::move(a) casts a to an rvalue and this call is also ok
}

これは、値によってパラメーターを受け取る関数が、左辺値と右辺値の両方を受け取ることができることを示しています。

追加するとします。

void g(int &) {}

その場合、最初の呼び出し は、非左辺値のみを受け取ることができるため、g(a);あいまいになります。2 番目の呼び出しは、右辺値を取ることができないため、問題なく呼び出します。g(int &)constg(std::move(a))g(int)g(int &)

に置き換えg(int &)ますg(int &&)。後者の関数は、非const右辺値のみを取ることができます。したがって、呼び出しg(a)は問題なく、呼び出しますg(int)。しかし、g(std::move(a))今はあいまいです。

この時点で、3 つのオーバーロードを一緒にすると、2 つの呼び出しがあいまいになることが明らかになります。実際には、3 つのオーバーロードを持つ理由はありません。タイプに応じてT、ほとんどの場合、次のいずれかがあります

  1. g(T)また
  2. g(T&)また
  3. g(const T&)また
  4. g(const T&)g(T&&)
于 2013-09-19T07:41:37.847 に答える