Topic: [variadic templates] sizeof pack expansion as an argument of a class template partial specialization.


Author: snk_kid <korcanh@googlemail.com>
Date: Tue, 24 Nov 2009 17:42:38 CST
Raw View
Is the following illegal in the current working draft?

template < size_t Index, typename...Types >
struct foo { /* ... */ };

template < typename...Types >
struct foo<sizeof... (Types), Types...> { /* ... */ };

typedef foo<0, ...> result_type;

If so is this restriction really necessary because this would be
extremely useful when writing meta-functions. The closet thing I could
find in the n3000 is this:

14.6.5.9
"...
-- An argument shall not contain an unexpanded parameter pack. If an
argument is a pack expansion (14.6.3), it shall be the last argument
in the template argument list."

Which doesn't really answer the question.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Wed, 25 Nov 2009 11:44:40 CST
Raw View
snk_kid wrote:

> Is the following illegal in the current working draft?
>
> template < size_t Index, typename...Types >
> struct foo { /* ... */ };
>
> template < typename...Types >
> struct foo<sizeof... (Types), Types...> { /* ... */ };
>
> typedef foo<0, ...> result_type;
>
> If so is this restriction really necessary because this would be
> extremely useful when writing meta-functions. The closet thing I could
> find in the n3000 is this:
>
> 14.6.5.9
> "...
> -- An argument shall not contain an unexpanded parameter pack. If an
> argument is a pack expansion (14.6.3), it shall be the last argument
> in the template argument list."
>

This doesn't appear to be valid because of 14.6.5/9b1: "A partially
specialized non-type argument expression shall not involve a template
parameter of the partial specialization except when the argument expression
is a simple identifier.". I wonder about the reason of this, though.

With regard to the text you quoted - the parameter pack is expanded because
of 5.3.3/5: "The parameter pack is expanded (14.6.3) by the sizeof...
operator.". So, the parameter is not unexpanded, and the construct
"sizeof...(Types)" does not appear to be a pack expansion (it seems to be
intuitive to have "pack is expanded <=> construct is a pack expansion", but
that doesn't appear to be the case).

"sizeof...(Types)" of course is a non-deduced context for "Types", but the
pack is deduced by the remaining arguments, and thus the value of "Types" in
sizeof will be found (14.9.2.5/4). You can get the same functionality by
introducing Another Level of Indirection, i think:

template < typename Index, typename...Types >
struct foo_impl { /* ... */ };

template <typename...Types >
struct foo_impl< std::integral_constant< size_t, sizeof... (Types) >,
                  Types... >
{ /* ... */ };

template< size_t Index, typename ...Types >
struct foo : foo_impl< std::integral_constant< size_t, Index >, Types... >
{ };


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]