你可以使用這個(恐怖)技術,這將導致如果A
進行實例化一個類型B
不具有公共void Foo(float)
成員,試圖通過採取特定指針到成員類型的編譯失敗它。
template <class B>
class A
{
public:
void Foo(B& b)
{
static_cast<void (B::*)(float)>(&B::Bar);
b.Bar(0.5);
}
};
(Demo of a resulting compilation failure)
如果你想,雖然,那麼你需要使用b.Bar(0.5f);
實際調用此方法。 0.5
是一個double
字面值,而不是float
字面值,所以您需要檢查以確保它具有正確的成員,但如果它有void Bar(double)
,則無論如何您都會這麼稱呼它。將常量改爲0.5f
可以解決這個問題。
請注意,由於採取指針沒有副作用,並且不使用結果,所以任何像樣的編譯器都會將其優化爲空操作。
你也可以去傳統SFINAE路線像這樣的東西:
template <typename T, typename TMethod>
class has_bar_method
{
private:
struct yes { char _; };
struct no { char _[2]; };
template <typename U, TMethod = &U::Bar>
static yes impl(U*);
static no impl(...);
public:
enum { value = sizeof(impl(static_cast<T*>(nullptr))) == sizeof(yes) };
};
像這樣來使用:
void Foo(T& b)
{
static_assert(has_bar_method<T, void (T::*)(float)>::value,
"T has method void Bar(float)");
b.Bar(0.5f);
}
現在,如果模板失敗實例,我們得到一個不錯的解釋原因的訊息:
prog.cpp:25:8: error: static assertion failed: T has method void Bar(float)
(Demo)
爲什麼B本身沒有模板? – NaCl 2014-11-05 23:01:41
那麼,爲了使事情順利,你想要在A?在我看來,你需要兩種不同的東西 - 可以檢查模板參數'B'是否有一個帶有浮點的方法'Bar'。但是,這本身不會阻止像'b.Bar(0);'這樣的東西。你能澄清嗎? – jrok 2014-11-05 23:08:16
你正在將字面值傳遞給'Bar'調用,我沒有看到你想讓編譯器爲你做的事情,你不能自己做。 – Aesthete 2014-11-05 23:14:15