替换失败不是错误,或者更简洁地说,SFINAE
但在您的特定情况下,您不需要 SFINAE、虚拟会员或任何类似的东西。
你只需要一个普通的重载函数。
int GetInt(A& t) { return t.GetInt(); }
int GetInt(const B& t) { return t.m; }
如果需要在不同版本之间共享代码,请重构它,以便有一个调用重载内联函数的模板,所有类型特定的行为都在内联函数中,所有共享行为都在模板中。
对于您“我有很多很多课程”的需求,SFINAE 或多或少看起来像这样:
template<typename T>
int GetInt(const T& t, int (T::*extra)() const = &T::GetInt)
{
return t.GetInt();
}
template<typename T>
auto GetInt(const T& t) -> decltype(t.m)
{
return t.m;
}
编辑:SFINAE 的现实要丑陋得多,至少在 C++0x 出现之前是这样。事实上,它开始看起来和 GMan 的回答一样糟糕。
struct A{ int GetInt() const { return 10; } };
struct B{ int m; };
template<typename T, int (T::*extra)() const>
struct has_mfunc
{
typedef int type;
};
template<typename T>
typename has_mfunc<T, &T::GetInt>::type GetInt(const T& t)
{
return t.GetInt();
}
template<typename T, typename U, U (T::*extra)>
struct has_field
{
typedef U type;
};
template<typename T>
typename has_field<T, int, &T::m>::type GetInt(const T& t)
{
return t.m;
}
int main(void)
{
A a;
B b;
b.m = 5;
return GetInt(a) + GetInt(b);
}