Search code examples
templatesc++11using

Default template arguments for the C++11 'using' type alias


I want to alias a type so that it can be given a template argument if necessary.

template<typename T, unsigned d>
struct value
{
    T a[d];
};

template<typename T=float>
using val=value<T, 2>;

int main()
{
    val v;      //should now be equal to val<float> v;
    val<int> w; //should also be valid.
    return 0;
}

G++ does not approve for some reason:

test.cpp: In function ‘int main()’:
test.cpp:12:13: error: missing template arguments before ‘v’
         val v;      //should now be equal to val<float> v;
             ^
test.cpp:12:13: error: expected ‘;’ before ‘v’

Do default template arguments not work with 'using'? If so, why does it not say so on the line the default argument is specified on?


Solution

  • Introduction

    Having default values for template-parameters in a alias-template is legal, but you cannot leave out <, and >, when you are later using said alias.

    template<class T = float>
    using val = value<T, 2>;
    
    val<>    v; // legal, decltype(v) => value<float, 2>
    val<int> w; // legal, decltype(w) => value<int,   2>
    

    What does the Standard say? (n3337)

    14.5.7p1 Alias templates [temp.alias]

    A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to be a alias-template. An alias template is a name for a family of types. The name of the alias template is a template-name.

    The above states that the name introduced by a template-alias is a template-name, and a template-name must be followed by a template-argument-list.

    14.2p1 Names of template specialization [temp.names]

    simple-template-id:
      template-name < template-argument-list_opt >
    
    template-name:
      identifier
    

    Note: Notice how the two <> are not optional when referring to a simple-template-id, and that a template-name by itself is merely an identifier, not a type.