2

I must be missing something obvious here because this really came to me as a surprise.

The following code gives me the error: error: missing template arguments before ‘a’

template<int n=0>
class A {};

...
A a;
...

Is there a reason why a template with 1 parameter declared with a default value has to be instantiated specifying a value for it?

Can someone quote the standard?

imreal
  • 10,178
  • 2
  • 32
  • 48
  • 5
    you don't need to specify it: `A<> a;` – W.F. Sep 18 '17 at 16:51
  • @W.F. Interesting, do you know why?. – imreal Sep 18 '17 at 16:52
  • similarly you can't call function with defaulted argument without braces. – W.F. Sep 18 '17 at 17:10
  • 1
    Possible duplicate of [Template default arguments](https://stackoverflow.com/questions/15373823/template-default-arguments) – Mauri Sep 18 '17 at 17:11
  • @imreal `A` isn't a class, it's a template. It makes no sense to declare a variable of a template -- you want a *particular instantiation*. `<>` is the clue to the compiler that you're trying to instantiate a template, just as W.F. points out that `()` is the clue that you're trying to invoke a function (even if you aren't passing any arguments). – cdhowie Sep 18 '17 at 17:20

2 Answers2

5

A is still a template class. But you can omit the template parameter though:

template<int n=0>
class A {};

int main() {
    A<> a;
  // ^^ 
    return 0;
}

See the live demo.


I think1 the relevant standard section is here

14.7 Template instantiation and specialization

...
3 An explicit specialization may be declared for a function template, a class template, a member of a class template or a member template. An explicit specialization declaration is introduced by template<>. In an explicit specialization declaration for a class template, a member of a class template or a class member template, the name of the class that is explicitly specialized shall be a simple-template-id. In the explicit specialization declaration for a function template or a member function template, the name of the function or member function explicitly specialized may be a template-id.
[Example:

 template<class T = int> struct A {
     static int x;
 };
 template<class U> void g(U) { }
 template<> struct A<double> { }; // specialize for T == double
 template<> struct A<> { }; // specialize for T == int
 template<> void g(char) { } // specialize for U == char
 // U is deduced from the parameter type
 template<> void g<int>(int) { } // specialize for U == int
 template<> int A<char>::x = 0; // specialize for T == char
 template<class T = int> struct B {
     static int x;
 };
 template<> int B<>::x = 1; // specialize for T == int

— end example ]


1)Sorry, I can't find a better standard cite / example. It doesn't cover exactly the OP's case, but demonstrates at least the same, that templates still need the <> angle brackets to be identified as templates (classes or functions).

user0042
  • 7,917
  • 3
  • 24
  • 39
3

possible workaround if it's important to disguise the nature of your object:

// the template class
template<int n=0>
class ReallyA {};

// an alias for the common case    
using A = ReallyA<0>;

A a;

This is how the standard library defines std::string, for example.

using string = basic_string<char>;
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142