Search code examples
c++templatesparametersdefault

Is it really impossible to skip template parameters with default arguments in C++, why does syntax suggest otherwise?


I've been trying to find a way to skip a template parameter not located at the end of the template parameter list, in a derived class that has been assigned a default in its base class.

I've done some research on this topic, also here on SO. While similar questions have been discussed on SO - many answers basically suggesting it doesn't work were related to very special cases like the hash map case here. Also I found this answer by "Potatoswatter", which in my opinion contradicts the impossibility of skipping such a parameter. In his answer he claims this declaration would be valid:

template< class A, class B = int, class C >
class X;

Assuming it is true that a template parameter may not be skipped (unless at the end of the argument list) such a declaration would make no sense at all. Since B is assigned a default value, but followed by C which has no default, in this case value B would always have to be assigned explicitly, rendering the assignment of int as default for B completely useless. The only scenario where the declaration of X above would make sense is one where one of the following declarations of Y would be valid:

class Y : public X<double, , const std::string&> { ... }

class Y : public X<A = double, C = const std::string&> { ... }

So is it really impossible to skip a template parameter that is not located at the end of the template parameter list when deriving a specialized class?

If it is impossible why so, and why does legal syntax apparently suggest otherwise (see class X example above)?

If it is in fact not impossible, how can one skip a template argument that has been assigned a default?


Solution

  • The relevant standardese is contained in "Template Parameters [temp.param]" (14.1).

    Essentially, a default argument may only be used if the parameter to which it applies is not followed by any non-pack parameters that do not have default arguments ([temp.param]/11). However, the syntax you quoted is usable in a declaration in the situation described by [temp.param]/10:

    The set of default template-arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are (8.3.6). [Example:

    template<class T1, class T2 = int> class A;
    template<class T1 = int, class T2> class A;
    

    is equivalent to

    template<class T1 = int, class T2 = int> class A;
    

    end example]