Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template partial specialisation

Can somebody explain why are those two specializations indistinguishable to the compiler (gcc 4.5.1 @ ideone)

http://ideone.com/9tNux

template <typename... T> struct S;

template<typename A, typename B, typename... C>
struct S<A, B, C...> {
   int f() {return 1;}
};

template<typename... A, typename... C>
struct S< S<A...>, C...> {
   int f() {return 2;}
};

and when I try to instantiate S<S<a, b>, a, b> o2; compiler complains:

prog.cpp:20:21: error: ambiguous class template instantiation for 'struct S<S<a, b>, a, b>'
prog.cpp:6:22: error: candidates are: struct S<A, B, C ...>
prog.cpp:11:33: error:                 struct S<S<A ...>, C ...>
prog.cpp:20:21: error: aggregate 'S<S<a, b>, a, b> o2' has incomplete type and cannot be defined

And when the last specialization is changed to:

template<typename... A, typename B, typename... C>
struct S< S<A...>, B, C...> {
   int f() {return 2;}
}

everything works fine.

like image 367
Predrag Avatar asked Aug 08 '11 20:08

Predrag


People also ask

What is meant by template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

What is the class template?

A class template provides a specification for generating classes based on parameters. Class templates are generally used to implement containers. A class template is instantiated by passing a given set of types to it as template arguments.

What is class template with multiple parameters?

Explanation of the code: In the above program, the Test constructor has two arguments of generic type. The type of arguments is mentioned inside angle brackets < > while creating objects.

What is Typename C++?

Use the keyword typename if you have a qualified name that refers to a type and depends on a template parameter. Only use the keyword typename in template declarations and definitions.


2 Answers

My understanding of the issue:

typedef S<S<a, b>, c, d> S2;

Here S<a,b> matches the second specialization better. However, c, d is a better match for the remaining arguments of the first specialization (single arg + list vs list). Hence it is 1:1.

If you comment in B in the second specialization, then the second specialization matches better because it is more specialized for the first argument (S<...>) and the rest are equally good.

like image 89
UncleBens Avatar answered Oct 05 '22 10:10

UncleBens


I made a mess of this; it should be OK now, but credit is due to @UncleBens below who got it right (and should get the "accept").


Without the B in your third version, you have two partial specializations which are equally specific when you instantiate S<S<X,Y,Z>, T1, T2, T3>:

  • First PS: A = S<X,Y,Z>, B = T1, C... = T2, T3.
  • Second PS without B: A... = X,Y,Z, C... = T1, T2, T3.
  • Second PS with B: A... = X,Y,Z, B = T1, C... = T2, T3.

This does not establish comparable elements in the partial specialisation ordering!

Note that you can say template <typename ...> struct S; and template <typename A, typename ...B> struct S<A, B...>; and the second one is more specific than the first because it has more non-variadic parameters.

But on the other hand, without the B, when you say S<S<X,Y,Z>,T1,T2,T3>, then the first argument matches better in the second PS, but the remaining arguments match better in the first PS. With the B in place, though, the second PS is more specific.

Compare this to the partial specialization that is actually more specific:

template <typename ...A, typename B, typename ...C>
struct S<B, std::tuple<C...>, std::tuple<C...>> { /* ... */ };

Now it is clear how whether a given instance matches the specialization, or only the general form. The specialization has a fixed number of parameters (3), so it wins over another specialization with a variable number of arguments.

like image 42
Kerrek SB Avatar answered Oct 05 '22 10:10

Kerrek SB