你可以使用这个(恐怖)技术,这将导致如果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