Search code examples
c++templatessfinae

Why does using a fundamental type as a base-class compile sometimes?


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?


Solution

  • 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.