3

Question for standard gurus.

Trying to respond to another question, I came to doubt about the well-formedness of a code.

As far I know, the following code is ill-formed

int main ()
 {
   std::tuple<>  a;

   std::get<0>(a);
 }

because a call to std::get<I>(t), when t is a std::tuple<Ts...>, is ill-formed when I is outside the range [0, sizeof...(Ts)[.

In this case sizeof...(Ts) is zero, so the range [0, 0[ is empty, so std::get<I>(a) is ill-formed for every index I.

But when std::get<I>(a) is expanded through an empty variadic pack?

I mean: the following code

#include <tuple>

template <typename ... Args>
void bar (Args const & ...)
 { }

template <std::size_t ... I>
void foo ()
 {
   std::tuple<> a;

   bar( std::get<I>(a) ... );
 }

int main ()
 {
   foo<>();
 }

that uses a ill-formed (?) call (std::get<I>(a)) but zero-time variadic expanded (sizeof...(I) is zero), is well-formed or ill-formed?

max66
  • 65,235
  • 10
  • 71
  • 111

1 Answers1

6

[temp.res]/8:

The program is ill-formed, no diagnostic required, if:

  • [...]
  • every valid specialization of a variadic template requires an empty template parameter pack, or
  • [...]
T.C.
  • 133,968
  • 17
  • 288
  • 421
  • Note that it is ill formed as OP tried to simplify the problem :-/ (as original is nearer that `get(tuple_of_size{})...`). – Jarod42 Sep 28 '17 at 17:38
  • As an aside, this means when implementing apply it is tricky to avoid this trap. – Yakk - Adam Nevraumont Sep 28 '17 at 17:41
  • @Jarod42 - sorry: with "as original" do you mean from the question I've linked? – max66 Sep 28 '17 at 17:42
  • @max66: yes indeed. – Jarod42 Sep 28 '17 at 17:44
  • @Jarod42 - I see. But, if I'm not wrong, in that question (see the code linked in "compiler explorer") `var` is a `std::tuple<>` (and the warning disappear when is a `std::tuple`). – max66 Sep 28 '17 at 17:46
  • @T.C. - thanks for your answer that show me a rule I didn't know and solve the doubt I've expressed in this question. But I'm not sure how it should be interpreted this rule for templates with two or more parameter packs. But I suppose is better if I write another question. Thanks again. (p.s.: I hate "no diagnostic required") – max66 Sep 30 '17 at 12:06
  • @T.C. - added a [new related question](https://stackoverflow.com/questions/46502745/template-well-formedness-and-zero-pack-length-rule); hoping you can give a look. – max66 Sep 30 '17 at 12:40
  • does this really apply to the OP question ? for example, one could specialize/overload std::get to work with an empty tuple, and given that the get template argument depends on foo template parameter, I don't think we can prove that *every* valid specialization requires an empty pack ... – Massimiliano Janes Sep 30 '17 at 16:10
  • @MassimilianoJanes A sufficiently clever compiler is free to use the knowledge that 1) no such `std::get` overloads/specializations are provided by the standard library and 2) no user code can add such overloads/specializations, on pain of UB. – T.C. Sep 30 '17 at 23:57
  • @T.C. I think the OP is interested in the general question concerning templates, rather than those using std:: members. Clearly, your comment does not apply to the general case ... – Massimiliano Janes Oct 01 '17 at 07:23
  • @T.C. secondly, I believe such a broad reading of the standardese goes against its orginal intent ( that is, early cathing of template errors ), see my answer ... – Massimiliano Janes Oct 01 '17 at 07:25
  • @T.C. at best, your answer should be completed with a quote concerning non overlodability/specializability of std members; note that it would suffice adding a std::get using directive and making an unqualified call to neutralize your argument ... – Massimiliano Janes Oct 01 '17 at 07:41
  • @MassimilianoJanes There's no non-`std` namespaces for ADL to look at for `std::tuple<>` in the instantiation context. – T.C. Oct 01 '17 at 08:13