1

First, I want to say that I know that the following is not possible in C++17, I am more interested in whether it could be possible.

Function templates and class templates differ in the aspect that the first declaration is possible while the second is not:

template<class ...Ts, class S>
void foo(S s);

template<class ...Ts, class S>
class bar;

In the accepted answer to this question it is pointed out that this is because the compiler can deduce S from the function parameter, while it cannot do that for the class. So for the first code, it can differentiate between the Ts and S and it cannot in for the second code.

While I am still a bit unsure, why the compiler cannot deduce S by virtue of using the last template parameter, I see why the function case is clearly superior.

But the following does compile

template<class ...Ts, class S>
void foo();

only one cannot call it in any way, since the compiler won't be able to deduce S. So theoretically, could one allow the declaration of bar to compile and outsource the error to whenever we want to use it? Then if we had no default constructor and a constructor like

bar::bar(S s, Ts... ts); // Edit: Added Ts which are necessary as @Nicol Bolas. And I am aware that it is weird to turn them around here but not in the template.

we could deduce S from this, whenever we initialize an object of type bar (except for copying/moving, but then one just takes the same type as the object passed in).

So why is this not possible? Is it because bar is a type and one should be able to use it without instantiating an object of that type?

n314159
  • 4,990
  • 1
  • 5
  • 20
  • 2
    Asking *why is this not possible* is usually not a very good question. Theoretically we could make the language work in any way we want. There are probably a lot of good things missing in the language still, that's why they're still releasing new standards every 3 years. – super Dec 05 '19 at 21:42
  • Also, you should probably clarify what you mean by *outsource the error to whenever we want to use it*. – super Dec 05 '19 at 21:44
  • 1
    *Is it because bar is a type and one should be able to use it without instantiating an object of that type?* Yes. If I want to make a `bar` I couldn't since both `int` and `double` would become part of the parameter pack. – NathanOliver Dec 05 '19 at 21:50
  • @super If we declare a function template that is unusable (see the second `foo` above), the declaration won't be a problem at all, but everytime you try to call it, the compiler will fail to deduce `S`. The same could be done for classes. – n314159 Dec 05 '19 at 21:51
  • 1
    @n314159: "*we could deduce S from this*" No, you can't. That would require being able to deduce some of the parameters from a guide, while others were provided directly. That's not allowed. Class deduction guides (implicit or explicit) must provide all parameters to the template. – Nicol Bolas Dec 05 '19 at 21:57
  • @n314159 I fail to see the point of allowing that if there is no way to instatiate the class. But it sounds perfectly possible to allow such a thing. – super Dec 05 '19 at 21:58
  • What problem would allowing this solve? You can just do this: `template class bar { using S = std::tuple_element_t>; };` – Indiana Kernick Dec 05 '19 at 22:17
  • @super It has not really a point^^ I find it just a bit weird that it is different for classes and functions. Actually I was a bit surprised that this was allowed for functions when I first found out. – n314159 Dec 05 '19 at 22:20
  • @Kerndog73 That would certainly be a possibility to do the same thing (even if it is a bit annoying that `S` would still be part of `Ts...`, its mostly easier to set the `S` before the `Ts...`). But this is a purely theoretical question, I have no code where I would need that. – n314159 Dec 05 '19 at 22:22

0 Answers0