0

さらに別のテンプレートの問題 ! 演算子 << のオーバーロードがある場合にオブジェクトを出力するテンプレート メソッドを取得しようとしています。ほとんどすべてが機能しており、g++ がオブジェクトの種類ごとに目的の特殊化を選択できるようにするために、enable_if を実装しました。

事は、オーバーロードされていないオブジェクトでは、非常にうまく機能します。しかし、オーバーロードされたものでは、両方の専門化が g++ の合理的な選択であり、コンパイルする代わりにあいまいなオーバーロード エラーが出力されます。

コードは次のとおりです。

template<typename T>
  static void   Print(Stream& out, T& param, typename enable_if<CanPrint<T>::value>::type = 0)
  {
    out << param;
  }

  template<typename T>
  static void   Print(Stream& out, T& param)
  {
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
  }

なぜそのようなことが曖昧なのか理解できます。それでも、それをより明確にする方法は考えられません...最初のオーバーロードが選択できない場合にのみ、2番目のオーバーロードが選択されることをコンパイラーに理解させるにはどうすればよいですか?

4

3 に答える 3

8

どちらの場合もT、最初の 2 つの引数としてストリームに続いて型を受け取る関数があるため、あいまいさが得られます。これはうまくいきます:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <typeinfo>

template <class T>
struct CanPrint { enum { value = 0 }; };

template <>
struct CanPrint<int> { enum { value = 1 }; };

template<typename T>
typename boost::enable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << param << std::endl;
}

template<typename T>
typename boost::disable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
}

int main()
{
    int i = 1;
    double d = 2;

    Print(std::cout, i);
    Print(std::cout, d);
}
于 2011-06-18T09:15:19.740 に答える
1

あいまいさは、デフォルトのパラメーター値が原因です。

呼び出しPrint(stream, whatever)は、デフォルトの 3 番目のパラメーターを使用して最初のバージョンに解決するか、3 番目のパラメーターを使用しない 2 番目のバージョンに解決できます。

デフォルト値を削除すると、コンパイラが理解します。それ以外の場合は、常に両方を選択できます。

于 2011-06-18T09:06:10.893 に答える
1

これはテンプレートとは何の関係もないと思います。この方法でオーバーロードされたフリー関数は、同じあいまいなエラーを引き起こします。

この簡単なコード例を確認してください。これは、テンプレートの例で行っていることと似ています:

void doSomething(int i, int j, int k );
void doSomething(int i, int j, int k = 10);


void doSomething(int i, int j, int k)
{

}

void doSomething(int i, int j)
{

}


int main()
{
    doSomething(10,20);
    return 0;
}

エラーは次のとおりです。

prog.cpp:18: error: call of overloaded ‘doSomething(int, int)’ is ambiguous
prog.cpp:5: note: candidates are: void doSomething(int, int, int)
prog.cpp:10: note:                 void doSomething(int, int)

明らかに、デフォルト引数だけに基づいてこの方法で関数をオーバーロードすることはできません。

于 2011-06-18T09:07:03.723 に答える