Substitution Failure Is Not An Error, or more compactly, 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;
}
EDIT: Реальность 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);
}
Возможно, вам стоит изучить виртуальные функции и полиморфизм. – JoshD
Если вы не предполагаете, что у ваших классов-экземпляров, отличных от 'GetInt', у всех есть член 'int', называемый' m'. Я не вижу, как вы можете расширять его без специализаций для каждого. Какова стандартная реализация шаблона вашей функции? –
Вы не можете заставить эту функцию работать, потому что 'GetInt' не const, а' t' есть. – GManNickG