This compiles (tested with GCC 9 and Clang 9):
template<typename U>
struct inherit : U { };
int test(inherit<int> arg);
But this does not:
int test(inherit<int> arg) { }
Why does the first one compile?
int test(inherit<int> arg);
is just a declaration. As such, we don't need to know about inherit<int>
yet. Because of that, the compiler will let it go.
With int test(inherit<int> arg) { }
you now have a definition and now we need to know about inherit<int>
so arg
can be destroyed when the function exits. At that point the template is instantiated and you get an error because it is invalid.
Another reason to ignore the declaration is that inherit
could later on get specialized for int
and that specialization might actually be a valid class since you could have something like
template<>
struct inherit<int> { };
If you were to add that between int test(inherit<int> arg);
and int test(inherit<int> arg) { }
then the code would now compile since inherit<int>
is now a valid type.