3

この例では、いくつかのオーバーロードが含まれています。

#include <iostream>

class T
{
   public:
      operator const wchar_t *(void) const
      {
         std::cout << "Conversion" << std::endl;
         return L"Testing";
      }
};

template <class Elem>
class A
{
};

template <class T>
void operator <<(A<T> &, const T *)
{
   std::cout << "1" << std::endl;
}

template <class T>
void operator <<(A<T> &, const void *)
{
   std::cout << "2" << std::endl;
}

int main(void)
{
   A<wchar_t> test;
   T          source;

   test << L"1";
   test << static_cast<const wchar_t *>(source);
   test << source;
}


そしてその出力:

1
Conversion
1
Conversion
2


私の質問は-なぜvoid operator <<(A<T> &, const void *)声明を求められているのtest << source;ですか?誰かがこのケースをカバーする規格の特定の部分を引用できますか?

4

3 に答える 3

4

テンプレート引数の推論では、ユーザー定義の暗黙的な変換が考慮されていないためです。結果はあなたが書いたときです:

test << source;

、コンパイラはT最初の関数テンプレートに適したものを見つけることができませんでした。それはあなたと同じタイプのTようなものを見つけようとしていますが、それは不可能です。引数の推定は失敗し、テンプレートのインスタンス化はオーバーロードセットに追加されません。2番目の関数テンプレートの2番目のパラメーターにはテンプレート引数がないため、失敗する引数の推定はなく、結果のインスタンス化はオーバーロードセットの唯一のメンバーになり、最終的に選択されます。T const*T

于 2012-02-08T17:02:10.903 に答える
0

テンプレート引数の暗黙的な推論では、ユーザー定義の暗黙的な変換は考慮されません。そのため、呼び出しtemplate <class T> void operator <<(A<T> &, const T *)は最初の引数からのものであると推測Tされますwchar_tが、2番目の引数はTの代わりになりconst wchar_t*ます。したがって、コンパイラはその演算子と一致しません。

問題はtemplate <class T> void operator <<(A<T> &, const void *)異なって見えます:最初の関数の引数からであるTと推定されます。wchar_t2番目の引数はconst wchar_t*、ユーザー定義の変換によって暗黙的に変換できます。その後、組み込み変換によって暗黙的ににキャストできますconst void*。したがって、この関数はこれらの引数を使用して呼び出すことができ、他の関数を推定できなかったために使用されます。

于 2012-02-08T16:54:41.563 に答える
0

Tの暗黙の変換を使用しwchar_tます。どのタイプもに変換可能でvoid*あるため、コンパイラはそのバージョンのを呼び出しますoperator<<。から暗黙的T*に取得する方法がなかったため、演算子は候補にはなりませんでした。オペレーターにするつもりでしたか?T*TT& <<

于 2012-02-08T16:45:11.490 に答える