2013-04-26 33 views
5

爲什麼這個編譯:爲什麼我的模板不能重載?

class Testable { 
public: 
    template <bool flag> 
    typename std::enable_if<flag>::type 
    void foo() { cout << "Yay" << endl; } 

    template <bool flag> 
    typename std::enable_if<!flag>::type 
    void foo() { cout << "Nay" << endl; } 
}; 

但如果我定義使用的默認類型,像這樣既FOOS:

template <bool flag, typename = typename std::enable_if<flag>::type> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, typename = typename std::enable_if<!flag>::type> 
    void foo() { cout << "Nay" << endl; } // (B) 

我得到這個錯誤(第一線指向的(B)定義,第二個指向(A)):

error: 'template<bool flag, class> void Testable::foo()' cannot be overloaded 
error: with 'template<bool flag, class>> void Testable::foo()' 

回答

5

編譯器會抱怨由於兩個功能模板具有相同的簽名。款C++ 11標準指定了一個函數模板的簽名是通過定義的1.3.18:

<function template>名稱,參數類型列表(8.3.5),封閉命名空間(如果有的話),返回類型和 模板參數列表

如您所見,默認模板參數不是簽名的一部分。

你可以解決此問題,通過改變你的Testable定義如下:

class Testable { 
public: 
    template <bool flag, typename std::enable_if<flag>::type* = nullptr> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, typename std::enable_if<!flag>::type* = nullptr> 
    void foo() { cout << "Nay" << endl; } // (B) 
}; 
+0

這實際上仍然不能編譯我(在gcc4.6.3上)。當我嘗試調用foo ()時,我得到'沒有與'Testable :: foo()'調用匹配的函數。 – Barry 2013-04-26 18:03:28

+0

@Barry你必須有'foo'模板參數。沒有什麼可以爲你推演的。你試過'obj.foo ();'? – WhozCraig 2013-04-26 18:04:22

+0

@WhozCraig - 是的,我的整個主要只是'Testable t; t.foo ();' – Barry 2013-04-26 18:06:17

0

如前所述,兩個功能不能具有相同的簽名。

但是,我有一個不同的修復程序。

template<std::size_t> 
struct secret_enum { enum class type {}; }; 
template<bool b, std::size_t n=0> 
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type; 

class Testable { 
public: 
    template <bool flag, EnableIf<flag, 0>...> 
    void foo() { cout << "Yay" << endl; } // (A) 

    template <bool flag, EnableIf<!flag, 1>...> 
    void foo() { cout << "Nay" << endl; } // (B) 
}; 

,你列舉你的過載與01等,產生一個可能的類型,你再...說「0以上的這些」,這和產生的類型基本上不可能產生enum實例。

不幸的是,這在3.2中不起作用。它在gcc 4.8中。

相關問題