3
votes

On the one hand there is the rule [temp.res]/8.3 which states that if every valid specialization of a variadic template requires an empty template parameter pack the program is ill-formed and no diagnostic is required. On the other hand one can imagine the situation when one can explicit instantiate any desired specialization of the template but cannot call it [temp.mem]/5.note-1, e.g.:

struct foo {
    template <class... Ts>
    foo() { }
};

template
foo::foo<int, float, double>();

Is the code well-formed or the fact one cannot call any valid specialization apart from the one with empty template parameter pack violates the [temp.res]/8.3 rule?

1

1 Answers

1
votes

This reminds me a little of the Haskell function absurd:

-- | Since 'Void' values logically don't exist, this witnesses the logical
-- reasoning tool of \"ex falso quodlibet\".
absurd :: Void -> a

What this means is a function that takes an instance of Void and returns an instance of any type. What does it mean to say that a function can invent an instance of any type out of thin air from nothing? It doesn't matter, because you can't come up with an instance of Void to pass into it.

Similarly here. In my opinion, the code is well-formed, if silly. There is nothing here that requires Ts... to be an empty pack. If Ts... were non-empty, the program would still be fine. The fact that there's no way to make Ts... non-empty seems orthogonal - if you could come up with a construct that made a non-empty Ts that led to the program being ill-formed, maybe [temp.res]/8.3 would apply - but you can't so... ¯\_(ツ)_/¯