まずADLって何よ?
関数呼び出し式において、関数名についてスコープ解決演算子 ::
を使用しなかった時、実引数の存在する名前空間が探索される。 1
この時、引数がクラステンプレートであれば、テンプレート引数の型が定義されている名前空間も探索対象となる。
#include <iostream>
#include <utility>
using namespace std;
namespace ns
{
struct s{};
void swap( s, s ) { cout << "ns" << endl; }
}
int main()
{
using std::swap;
ns::s v;
swap( v, v );
}
クラステンプレートのインスタンス化
クラステンプレートをインスタンス化する時、そのテンプレート引数の型の定義が定義されている名前空間を探索対象にはしない。
何故なら、関数呼び出し式ではないからだ。
例えば、以下のコードはビルドが通らない。
#include <limits>
namespace ns
{
template< class C >
struct numeric_limits {};
struct s {};
template<>
struct numeric_limits< s >
{
static constexpr const bool is_exact = true;
};
}
int main()
{
using std::numeric_limits;
static_assert( numeric_limits< ns::s >::is_exact, "test" );
}
どうすればいいのか
臆せず堂々と特殊化しろ。名前空間 std
だろうがテンプレートの特殊化なんだ、未定義の動作にならないはずだ! 2