The reason that the first example gives an error is that name lookup does not take into account the return type. But when the actual function body is being generated in the expression where it is being called, the compiler will use Some::abc
and find a discrepancy.
typedef int abc;
class Some{
public:
abc foo() { return abc(); } // during lookup/resolution, "abc" is known to be int, return type is not considered
typedef double abc;
};
int main()
{
Some s;
int x = s.foo(); // kaboom, return type is double.
}
In your second example, the type redefinition is inconsequential because during name lookup, abc
is known to be an int, because the definition of the inner typedef has not yet been seen. There are no consequences during the instanation of the function at the call site, because the return type is also int. There is simply no mismatch.
typedef int abc;
class Some{
public:
int foo(abc) { return int(); } // during lookup/resolution, "abc" is known to be int
typedef double abc; // this will not have been seen yet in the previous line
};
int main()
{
Some s;
int x = 0;
s.foo(x); // OK, x is of type int
}