2

The following code comes from an answer to another question, and it works. I tested it with recent versions of GCC, Clang, ICC and MSVC. But I don't understand which part of the standard allows this kind of construction, could you please help?

template<class F, class Alloc> class C; //undefined
template<class T, class... Args, class Alloc>
class C<T(Args...), Alloc> {
    // implementation
};

The C++ standard provides constraints on how parameter packs can be used in primary class templates, but I can't figure out how these apply to partial specializations.

So my question is: where are the rules of placement for parameter packs in the context of partial template specialization defined in the C++ standard?

Community
  • 1
  • 1
Drealmer
  • 5,578
  • 3
  • 30
  • 37
  • What's your actual question? How does partial specialization work? – Barry Jun 06 '16 at 13:28
  • 1
    You mean like [here](http://eel.is/c++draft/temp.class.spec#8)? – Barry Jun 06 '16 at 13:39
  • Thanks, that looks indeed like right on topic. But then it says "If an argument is a pack expansion ([temp.variadic]), it shall be the last argument in the template argument list." which seems to contradict the example, or am I missing something? – Drealmer Jun 06 '16 at 13:46
  • 2
    @Drealmer `T(Args...)` is not a pack expansion argument. `Args...` would have been a pack expansion argument – bolov Jun 06 '16 at 13:48
  • alright, this is starting to make sense, thanks guys! but then does this say something about the placement of parameter packs inside the parameter list of a specialization? (since the part about the argument list is indeed not a problem) – Drealmer Jun 06 '16 at 13:55

1 Answers1

1

While not a formal and technically correct way of understanding how partial specialization works (check out the cppreference page for a more technical explanation), you can think of the code snippet you posted in terms of "pattern matching" (just as an intuition):

// `C` is a template class that takes two types as template parameters.
template<class F, class Alloc> class C; 

// I'm going to specialize `C` so that:
// * The first type will be a function signature type, where the return
//   type is going to be matched by `T` and the argument types will be 
//   matched by `Args...`.
// * The second type will be an user-provided `Alloc` typename.
template<class T, class... Args, class Alloc>
class C<T(Args...), Alloc> { /* ... */ };

Let's say I instantiate C like this:

using My_C = C<int(float, char), std::allocator<int>>;
My_C c;

Very roughly speaking, My_C will "match" the C<T(Args...), Alloc> partial template specialization as follows:

int ( float, char )     std::allocator<int>
^^^   ^^^^^^^^^^^       ^^^^^^^^^^^^^^^^^^^
 T  (    Args...  )           Alloc
^^^^^^^^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^
         F                    Alloc

int is "matched" by T, and float, char are "matched" by Args.... There's no reason why Args... should be restricted to be the last template parameter of C.

As you can see, it is not required for the Args... parameter pack to be the last template argument, as we're just using it to "provide a name" for the argument type list in the passed function signature.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • Mind explaining the downvote? I interpreted the question as *"I thought that parameter packs need to be at the end of parameter lists and I do not understand why this code works"*, and tried to give a non-formal interpretation of the role of `Args...` in the posted code snippet. – Vittorio Romeo Jun 06 '16 at 13:43
  • I don't understand the downvote either, it isn't mine. – Drealmer Jun 06 '16 at 13:45
  • We don't really have "pattern matching" in C++. Picking a partial specialization involves template deduction and partial ordering. – Barry Jun 06 '16 at 13:51
  • @Barry: I am aware of that, I used the "pattern matching" term to provide an intuition to easily understand the role of `Args...` in the snippet. I'll make it more clear in the answer that "pattern matching" is not happening on a technical level. – Vittorio Romeo Jun 06 '16 at 14:04