2010-12-06 7 views
4

次のコードを印刷:ミキシングテンプレート関数のオーバーロードと継承

generic 
overload 

しかし、私が望んでいたことは、過負荷や専門がない一般的なもの、両方のケースで呼び出されたということです。私は、テンプレートの特殊化と過負荷を混在させようとはしていません。これを達成するためのテンプレートマジックはありますか?

#include <iostream> 

class Interface {}; 
class Impl: public Interface {}; 

class Bar 
{ 
public: 
    template<typename T> void foo(T& t) { 
     std::cout << "generic\n"; 
    } 
    void foo(Interface& t) { 
     std::cout << "overload\n"; 
    } 
}; 
template<> void Bar::foo<Interface>(Interface& t) { 
    std::cout << "specialization\n"; 
} 

int main() { 
    Bar bar; 
    Impl impl; 
    Interface& interface = impl; 
    bar.foo(impl); 
    bar.foo(interface); 
    return 0; 
} 

答えて

5

二つの方法。

#include <boost/type_traits.hpp> 

class Interface {}; 
class Impl: public Interface {}; 

class Bar 
{ 
    template <class T> void foo_impl(T& value, boost::false_type) 
    { 
     std::cout << "generic\n"; 
    } 
    void foo_impl(Interface& value, boost::true_type) 
    { 
     std::cout << "Interface\n"; 
    } 
public: 
    template<typename T> void foo(T& t) { 
     foo_impl(t, boost::is_base_of<Interface, T>()); 
    } 

}; 

条件が満たされる場合はテンプレートを無効にし、非テンプレートのみを候補として残します。

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits.hpp> 

class Interface {}; 
class Impl: public Interface {}; 

class Bar 
{ 
public: 
    template<typename T> 
    typename boost::disable_if<boost::is_base_of<Interface, T>, void>::type foo(T& t) 
    { 
     std::cout << "generic\n"; 
    } 

    void foo(Interface&) 
    { 
     std::cout << "Interface\n"; 
    } 
}; 
2

特化した機能を利用するためには、コンパイラは&Implから&Interfaceにパラメータ変換を行う必要があります。関数のシグネチャの一致を検索する場合、完全一致が変換を必要とするものよりも優先されます。ジェネリックfoo<T>が完全に一致するので、それが過負荷と専門機能の両方の上に出て勝ち。

0

テンプレート定義関数を作成することができます:Interface&パラメータを取りますが、定義されたものよりも一致です

void Bar::foo<Impl>(Impl& t) 

あなたは、おそらくこのように、スーパークラスの機能をより良いマッチングを行う必要があります。

class Bar 
{ 
    struct fallback { fallback(int) {} }; 
    template<typename T> void foo(T& t, fallback) { 
     std::cout << "generic\n"; 
    } 
    void foo(Interface& t, int) { 
     std::cout << "overload\n"; 
    } 
public: 
    template<typename T> void foo(T& t) { 
     foo(t, 0); 
    } 
}; 

だからあなたは内部の型テストを必要と思い、実際にhttp://ideone.com/IpBAv

を参照してください、しかし動作していないよう サブバージョンがInterfaceの汎用バージョンです。引数はインターフェイスから派生しているかどうかをテストするtype_traitsを使用して

+0

私が最初にこのコードを見たとき、私はGCCがそれが悪いと思うのと同じ理由でそれが悪いと思った。しかし、考え直しに、私は他のすべては –

+0

@Johannes等しい場合非テンプレート関数が関数テンプレート特殊よりも一致しているので、これは、非テンプレートに解決すべきだと思う:あなたが解決策を知っていますか? 「他のすべてが等しい場合、」非テンプレートは、そのパラメータのいずれかのためのより悪いの変換を持っていない場合は、」言うべきので、それは本当ではない、とテンプレートは、そのパラメータのいずれかのためのより良い変換を持っていない: –

+0

いいえ、私の上記のコメントを無視してください"私の非常に最初のコメントが言ったように、これは* *クリスクロスです:http://stackoverflow.com/questions/3519282/why-is-this-ambiguity-here/3525172#3525172、およびGCCは正しいです。 –

関連する問題