Substitution Failure Is Not An Error, or more compactly, SFINAE
But in your particular case, you don't need SFINAE, virtual members, or anything fancy like that.
You just need an ordinary overloaded function.
int GetInt(A& t) { return t.GetInt(); }
int GetInt(const B& t) { return t.m; }
If there's code that needs to be shared between the different versions, refactor it so that there's a template that calls an overloaded inline function, all type-specific behavior is in the inline function, and all shared behavior is in the template.
For your "I have many many classes" need, SFINAE would look more or less like this:
template
int GetInt(const T& t, int (T::*extra)() const = &T::GetInt)
{
return t.GetInt();
}
template
auto GetInt(const T& t) -> decltype(t.m)
{
return t.m;
}
EDIT: The reality of SFINAE is much uglier, at least until C++0x comes around. In fact it starts looking just as bad as GMan's answer.
struct A{ int GetInt() const { return 10; } };
struct B{ int m; };
template
struct has_mfunc
{
typedef int type;
};
template
typename has_mfunc::type GetInt(const T& t)
{
return t.GetInt();
}
template
struct has_field
{
typedef U type;
};
template
typename has_field::type GetInt(const T& t)
{
return t.m;
}
int main(void)
{
A a;
B b;
b.m = 5;
return GetInt(a) + GetInt(b);
}