例如,使用SFINAE(如果你接受一個C++ 11溶液)
#include <iostream>
#include <type_traits>
template <typename>
struct protocol_1
{ };
template <typename>
struct protocol_2
{ };
template<typename device, template<typename> class protocol>
class MyClass
{
public:
template<typename select, typename p = protocol<device>>
typename std::enable_if<
std::is_same<p, protocol_1<device>>::value, bool>::type
method()
{ return true; }
template<typename select, typename p = protocol<device>>
typename std::enable_if<
std::is_same<p, protocol_2<device>>::value, bool>::type
method()
{ return false; }
};
int main()
{
MyClass<int, protocol_1> m1;
MyClass<int, protocol_2> m2;
std::cout << m1.method<int>() << std::endl; // print 1 (true)
std::cout << m2.method<void>() << std::endl; // print 0 (false)
}
---編輯---
正如指出的Yakk(感謝!),這解決方案很薄弱,因爲使用可以被顯式化和循環發佈的模板默認值。
一個例子;與
MyClass<int, protocol_1>{}.method<void>();
就叫method()
的 「protocol_1」 版本,使用默認值p
;但explciting p
,如下
MyClass<int, protocol_1>{}.method<void, protocol_2<int>>();
被稱爲method()
的「protocol_2」版本在MyClass
的基礎上protocol_1
的istance爲了避免這個問題,有可能增加一個static_assert()
,在這兩個版本的method()
,檢查和強加p
等於默認值(protocol<device>
)
我的意思是......是遵循
template<typename select, typename p = protocol<device>>
typename std::enable_if<
std::is_same<p, protocol_1<device>>::value, bool>::type
method()
{
static_assert(std::is_same<p, protocol<device>>::value, "!");
return true;
}
template<typename select, typename p = protocol<device>>
typename std::enable_if<
std::is_same<p, protocol_2<device>>::value, bool>::type
method()
{
static_assert(std::is_same<p, protocol<device>>::value, "!");
return false;
}
所以
MyClass<int, protocol_1>{}.method<void, protocol_2<int>>();
生成編譯器錯誤。
請注意,這種方法是非常脆弱的,因爲如果在沒有人通過模板參數2的情況下,主體只有在有效的情況下才有效,那麼您將得到一個不良診斷需要的程序。更糟的是沒有編譯器會診斷問題;你的代碼看起來很完美。 – Yakk
@skyp搜索「無需診斷」,標準中只有十幾個。有關模板的必須具有有效的專業化(這意味着標準中的內容與通俗不同) – Yakk
@Yakk明白了。謝謝。 – skypjack