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

  • Follow


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                      ]

0
Reply korcanh (3) 11/25/2009 1:42:38 AM

Just to note that I know I can achieve the following by using a helper
meta-function like so:

template < const size_t N, typename... Types >
struct foo_helper
{
     static const size_t Index = sizeof...(Types) - N;
    // ....
};

template < typename... Types >
struct foo_helper< 0, Types... > { ... };

template < typename ... Types >
struct foo : foo_helper<sizeof... (Types), Types...> {...};

However there doesn't seem to be any reason to not allow for what I
mentioned in the first post.

-- 
[ 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                      ]

0
Reply snk_kid 11/25/2009 7:44:04 PM


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                      ]

0
Reply Johannes 11/25/2009 7:44:40 PM

On Nov 25, 12:42 am, snk_kid <korc...@googlemail.com> 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;

The variable argument lists confuse the issue, because I think you're
misunderstanding partial specialization. I've failed to come up with
the standard reference, but basically, a partial specialization does a
pattern matching against the template arguments to use a different
definition - but the important thing is, any template argument list
supplied to the template must be valid for the primary template. The
specializations only come into play after that.
In other words, foo<int, float>, which seems what you want to write,
is not valid, because the foo template expects a non-type parameter of
type size_t in the first position. The partial specialization doesn't
change this.

Now, if your partial specialization is valid (I have no idea if it
is), this only means that if I write foo<1, int, float>, the primary
definition is chosen, whereas if I write foo<2, int, float>, pattern
matching resolves sizeof...(Types) to 2 and sees that the partial
specialization matches; this definition is chosen instead.


--
[ 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                      ]

0
Reply CornedBee 11/28/2009 1:57:34 AM

>
> The variable argument lists confuse the issue, because I think you're
> misunderstanding partial specialization. I've failed to come up with
> the standard reference, but basically, a partial specialization does a
> pattern matching against the template arguments to use a different
> definition - but the important thing is, any template argument list
> supplied to the template must be valid for the primary template.
>

Yes I'm aware of that already.

> The specializations only come into play after that.
> In other words, foo<int, float>, which seems what you want to write,
> is not valid, because the foo template expects a non-type parameter of
> type size_t in the first position. The partial specialization doesn't
> change this.

Where have I mentioned that I want anything like a foo<int, float>?
I'm talking about variadic templates here where "sizeof... (Types)"
gives the size of the type list, that would be valid template argument
for non-type parameter.

>
> Now, if your partial specialization is valid (I have no idea if it
> is), this only means that if I write foo<1, int, float>, the primary
> definition is chosen, whereas if I write foo<2, int, float>, pattern
> matching resolves sizeof...(Types) to 2 and sees that the partial
> specialization matches; this definition is chosen instead.
>

Now I'm confused with what you just said earlier, I can't tell if you
understand that I'm talking about variadic templates & you understand
them or not.

-- 
[ 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                      ]

0
Reply snk_kid 11/30/2009 5:25:04 AM

On Nov 30, 4:25 am, snk_kid <korc...@googlemail.com> wrote:
>
>
> > Now, if your partial specialization is valid (I have no idea if it
> > is), this only means that if I write foo<1, int, float>, the primary
> > definition is chosen, whereas if I write foo<2, int, float>, pattern
> > matching resolves sizeof...(Types) to 2 and sees that the partial
> > specialization matches; this definition is chosen instead.
>
> Now I'm confused with what you just said earlier, I can't tell if you
> understand that I'm talking about variadic templates & you understand
> them or not.

Yes, I understand that you're talking about variadic templates and I
understand them.
What I apparently don't understand is what you want to do. What is the
code you want to write as a client of the example you presented above,
and what is it supposed to achieve? I was under the impression that
you want to write
foo<int, float>
and it should have the same effect as foo<2, int, float>.
Alternatively, you might want to have the instantiations foo<1, int,
float> and foo<2, int, float> and you want to special-case the
implementation of the latter, because the integral argument is the
same as the number of elements in the parameter pack.

What really confuses me is your second post, where you show a
workaround. However, this workaround presents the client with a foo
that has a different parameter list, so I don't see the equivalency.

Sebastian


-- 
[ 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                      ]

0
Reply CornedBee 11/30/2009 8:22:03 PM

5 Replies
88 Views

(page loaded in 0.09 seconds)

Similiar Articles:

7/18/2012 2:49:55 PM


Reply: