2010-12-06 26 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

使用type_traits來測試參數是否來自Interface的兩種方法。

#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

模板定義允許創建一個功能:

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

比你定義它採取Interface&參數的那些更好的匹配。

你必須要超功能更好的匹配,可能是這樣的:

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的子類。

+0

當我第一次看到那個代碼時,我認爲它是不合格的,因爲GCC認爲它是不合格的。但第二個想法,我認爲這應該解決非模板,因爲非模板函數是比功能模板專業化更好的匹配,如果一切都相等 – 2010-12-06 23:11:21