セクション§14.8.1/6(C ++ 03、およびC ++ 11にも当てはまると思います)は、次のように読み取るこのケースに適用されると思います。
[注:単純な関数名の場合、関数名が呼び出しのスコープ内に表示されていない場合でも、引数依存のルックアップ(3.4.2)が適用されます。これは、呼び出しがまだ関数呼び出し(3.4.1)の構文形式を持っているためです。ただし、明示的なテンプレート引数を持つ関数テンプレートが使用されている場合、呼び出しのポイントにその名前の関数テンプレートが表示されていない限り、呼び出しには正しい構文形式がありません。そのような名前が表示されない場合、呼び出しは構文的に整形式ではなく、引数に依存するルックアップは適用されません。そのような名前が表示されている場合は、引数依存のルックアップが適用され、他の名前空間に追加の関数テンプレートが見つかる場合があります。
[例:
namespace A {
struct B { };
template<int X> void f(B);
}
namespace C {
template<class T> void f(T t);
}
void g(A::B b) {
f<3>(b); //ill-formed: not a function call
A::f<3>(b); //well-formed
C::f<3>(b); //ill-formed; argument dependent lookup
// applies only to unqualified names
using C::f;
f<3>(b); //well-formed because C::f is visible; then
// A::f is found by argument dependent lookup
}
—end example] —end note]
テンプレート引数を明示的に渡し、呼び出したサイトに同じ名前のテンプレートがないため、ケースはADLをトリガーしませんdynamic_pointer_cast
。
ADLを有効にするための1つのトリックは、以下に示すように、同じ名前のダミーテンプレートをコードに追加することです。
#include <memory>
struct A {};
struct B : A {};
template<int> //template parameter could be anything!
void dynamic_pointer_cast(); //ADD this. NO NEED TO DEFINE IT
int main()
{
auto x = std::make_shared<A>();
if (auto p = dynamic_pointer_cast<B>(x)); //now it should work through ADL
}