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 ]