Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the scopes of default template arguments?

The standard (§14.1) Template parameters says:

A template-parameter of a template template-parameter is permitted to have a default template-argument.

Now consider following code :

#include <iostream>

using namespace std;

struct A {};
struct B {};

template<typename T = A>
struct X;

template<>
struct X<A> {
   static void f() { cout << 1 << endl; }
};

template<>
struct X<B> {
   static void f() { cout << 2 << endl; }
};

template< template<typename T = B> class C>
void g() {
   C<>::f();
}

int main() {
   g<X>();
}

It's output is:

out put :2

In this case, the template template-parameter is C.
But I don't understand why C<B>::f() is called inside g().

like image 759
Adib Avatar asked Nov 25 '16 20:11

Adib


3 Answers

This declaration

template< template<typename T = B> class C>
void g() {
   C<>::f();
}

is equivalent to

template< template<typename T = B> class C>
void g() {
   C<B>::f();
}

Thus this call

   g<X>();

is equivalent to the call of the function

void g() {
   X<B>::f();
}

The paragraph #14.1.14 of the C++ Standard contains corresponding examples

14 A template-parameter of a template template-parameter is permitted to have a default template-argument. When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter. [Example:

template <class T = float> struct B {}; 
template <template <class TT = float> class T> struct A {
 inline void f();
 inline void g(); 
}; 
template <template <class TT> class T> void A<T>::f() {
 T<> t; // error - TT has no default template argument 
} 
template <template <class TT = char> class T> void A<T>::g() {
 T<> t; // OK - T<char> 
} 

—end example]

like image 187
Vlad from Moscow Avatar answered Oct 22 '22 10:10

Vlad from Moscow


Think about what would happen without default template template parameter for g():

template< template<typename T> class C>
void g() {
   C<>::f();
}

would be ill-formed as the use of C would require a template parameter inside the definition of g(). Now that you provided B as a default, the definition of template g() is well formed and the default for the template template parameter of X is irrelevant.

like image 24
Maarten Hilferink Avatar answered Oct 22 '22 12:10

Maarten Hilferink


I think this is covered by N4567 14.1/14

A template-parameter of a template template-parameter is permitted to have a default template-argument. When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter. [Example:

    template <class T = float> struct B {}; 

    template <template <class TT = float> class T>
    struct A { inline void f(); inline void g(); };

    template <template> <class TT> class T> void A<T>::f() {
      T<> t; // error - TT has no default template argument
    }

    template <template <class TT = char> class> T> void A<T>::g() {
      T<> t; // OK - T<char>
    }

-- end example]

So the default template parameter of a template template parameter applies only in the scope where the default parameter is declared.
In the examples it is even switching the default template parameter for the template template parameter between the member function declaration and the member function definition.

like image 20
SirGuy Avatar answered Oct 22 '22 11:10

SirGuy