Search code examples
c++templatesc++17template-argument-deduction

Default template parameter cannot be used inside another template parameter?


I have a class template with a default value for the template parameter:

template<typename T = int>
class DefaultType : private std::array<T, 5> { };

and since c++17 this can be instantiated like a normal class

DefaultType obj; // equivalent to `DefaultType<>`

The same thing cannot be done if I use this type as an argument for another template:

// error: type/value mismatch at argument 1 in template parameter list for ...
class Foo : public std::vector<DefaultType> { };

yet, the above snippet does compile with DefaultType<>. (godbolt)

what's the reason for that? would a deduction guide help? and what about NTTPs?


Solution

  • This:

    DefaultType obj; 
    

    uses CTAD (class template argument deduction) which is available since C++17 and only in certain contexts:

    • any declaration that specifies initialization of a variable and variable template
    • new-expressions
    • function-style cast expressions
    • the type of a non-type template parameter:

    To instantiate DefaultType with the default argument in other contexts you still need to write DefaultType<>.

    I suppose the reason to have CTAD only in certain contexts is that those are the contexts where you always want an instantiation, but never the template.