This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/52008] [C++0x] ICE when adding partial specialization for variadic-templated structure


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52008

--- Comment #10 from Michal Malecki <ethouris at gmail dot com> 2012-04-23 12:38:47 UTC ---
(In reply to comment #9)
> (In reply to comment #8)
> > 2. The code is rejected the following way: the template specialization
> > definition is itself rejected because due to not covered explicitly all
> > explicit parameters (that is, all but parameter pack) this is not considered
> > template specialization.
> 
> Right, because the partial specialization doesn't specialize the Type1
> parameter, it is not more specialized than the primary template.

It's not the problem that it's "not more specialized" (because it is, as long
as we state it's correct), but rather that it's not correctly defined partial
specialization.

I have tried to find some confirmation in the C++ standard; I think the
14.5.5/4 should make things clear:

(...)
Specifically, the order of the template arguments is the sequence in which they
appear in the template parameter list.
(...)

There are no specific statements for template specializations in case of
variadic parameters. It's important because there are two theoretical
possibilities:

1. First there happens the parameter pack expansion, and then the potential
specialization is verified against the primary template. This way the
specialization can only be rejected if the resulting parameter list does not
match the primary template.

2. First the potential specialization is verified against the primary template,
and then the parameter pack is expanded. In this case the mentioned code is
invalid because the second definition cannot be considered partial
specialization of the tuple_sliced class.

By literally adhering to this rule in the standard, the #2 solution should be
taken. It would be also hard to apply #1 for templates that are also variadic
(to expand the parameter pack, it must be instantiated, and after
instantiation, specializations can no longer be considered).

So, this code should be rejected already at the place of definition of the
specialization, with the explanation, that the arguments passed to the
specialization must exactly match arguments defined in the primary template
(even if it's a parameter pack).

The only thing I have doubts of is whether this is then correct:

template <class A, typename... V> class X;
template <class B, class C, typename... V> class X<int, B, C, V...>;

According to the cited rule in the standard, it's not - the only allowed would
be <int, V...> or <C, V...>.

> You should rewrite your code the way I did, and then do something to address
> the ambiguity; possibly a third partial specialization.

It's not a problem to rewrite the above code so that it works as expected:

template<bool cond, typename TypeIfSo, typename TypeIfNot>
struct TypeIf { typedef TypeIfNot type; };

template<typename TypeIfSo, typename TypeIfNot>
struct TypeIf<true, TypeIfSo, TypeIfNot> { typedef TypeIfSo type; };

template <size_t B, typename Type1, typename... Types>
struct tuple_sliced
{
        typedef typename
                TypeIf<B==0,
                        tuple<Types...>,
                        tuple_sliced<B-1, Types...>
                >::type type;
};

Important thing is that the initial code, even though incorrect, should result
in correct rejection and error report.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]