4

次のコードを実行するときに、コンパイラがインターフェイス テンプレートを選択しないのはなぜですか? 追加の宣言/ヒントが必要ですか、それとも一般的に機能しませんか?

これが実際に可能かどうか、私はただ興味があります。

class Interface {
    public :
       virtual void Method() = 0;
       virtual ~Interface() { }
};

class Derived : Interface {
    public : 
       void Method() {
            cout<<"Interface method"<<endl;
       }
};

template<typename T> 
struct Selector {
    static void Select(T& o) {
        cout<<"Generic method"<<endl;
    }
};

template<> 
struct Selector<Interface> {
    static void Select(Interface& o) {
        o.Method();
    }
};

int i;
Selector<int>::Select(i)       // prints out "Generic method" -> ok
Derived d;
Selector<Derived>::Select(d);  // prints out "Generic method" -> wrong
                               // should be "Interface method"
4

3 に答える 3

6

これを試してください(および#include <type_traits>):

template <typename T, typename = void>
struct Selector
{
    static void Select(T & o)
    {
        std::cout << "Generic method" << std::endl;
    }
};

template <typename T>
struct Selector<T,
           typename std::enable_if<std::is_base_of<Interface, T>::value>::type>
{
    static void Select(Interface & o)
    {
        o.Method();
    }
};

デフォルトのテンプレート引数とenable_if組み合わせて、部分的な特殊化をガイドするために使用できることがわかりました。

于 2012-11-15T19:40:25.677 に答える
5

コンパイラは、最も近いバージョンの関数を選択します。パラメーターの正確な型を取る関数は、変換を必要とする関数よりも常に優先されます。この場合、テンプレート関数はすべてに一致するため、完全一致です。Interface特殊化では、パラメータを から に変換する必要がDerivedありますInterface

于 2012-11-15T19:36:47.320 に答える
0

これにより、目的の結果を得ることができます。

#include <iostream>
#include <type_traits>
using namespace std;

class Interface {
    public :
       virtual void Method() = 0;
       virtual ~Interface() { }
};

class Derived : public Interface {
    public : 
       void Method() {
            cout<<"Interface method"<<endl;
       }
};

template<typename T, typename S = void> 
struct Selector {
    static void Select(T& o) {
        cout<<"Generic method"<<endl;
    }
};

template<typename T>
struct Selector<T, typename enable_if< is_base_of<Interface, T>::value >::type> {
    static void Select(Interface& o) {
        o.Method();
    }
};

int main()
{
int i;
Selector<int>::Select(i);       // prints out "Generic method" -> ok
Derived d;
Selector<Derived>::Select(d);  // prints out "Generic method" -> wrong
                               // should be "Interface method"
}
于 2012-11-15T19:42:37.947 に答える