1

名前空間 に関数があります。この関数の仕事は、引数依存ルックアップを使用しns::fooて の呼び出しをディスパッチすることです。foo

namespace ns
{

template<typename T>
void foo(T x)
{
  // call foo through ADL
  foo(x);
}

}

fooクライアントが手動でインスタンス化せずに呼び出せるようにしたい、つまり:

bar x;
ns::foo(x);

いいえ

ns::foo<bar>(x);

もちろん問題は、よりもns::foo適切な一致がない場合、 が再帰的であることです。foons::foo

別の名前を付けたくないns::fooので、内部に設定されたオーバーロードから削除する方法はありますか?

4

2 に答える 2

4

fooディスパッチしたい先がns名前空間にない場合、これはうまくいくはずです:

namespace helper
{
    template<typename T>
    void _foo(T x)
    {
        // call foo through ADL
        foo(x);
    }
}

namespace ns
{
    template<typename T>
    void foo(T x)
    {
      ::helper::_foo(x);
    }
}

トリックは、foofromへの呼び出しが を_foo考慮ns::fooしないことです。これは、引数に依存する名前空間にないためです。の型がもちろんある場合を除きますx定義により再帰があります。ns

更新:の定義の直後にこのコードを配置する必要がありnamespace nsます:

namespace ns
{
     //your useful stuff here
}
namespace helper { /* template _foo */ }
namespace ns { /* template foo */ }

関数がまだ定義されていないため、helper::_foo関数を呼び出すことができないため、再帰はありません。template foo

于 2012-06-15T22:30:05.883 に答える
1

追加の引数を使用して ADL 関数を定義すると、別の型シグネチャが与えられるため、競合は発生しません。テンプレートをグローバル スコープで定義しましたが、nsスコープ内でも機能します。

namespace ns
{
   class A {};
   class B {};
   void foo(A, int) { std::cout << "adl: fooA" << std::endl; }
   void foo(B, int) { std::cout << "adl: fooB" << std::endl; }
}

template <typename T>
void foo(T t) {
   foo(t, 0);
}

int main()
{
   ns::A a;
   ns::B b;
   foo(a);    //calls ns::foo
   foo(b);    //calls ns::foo
}
于 2012-06-15T22:25:43.827 に答える