How can a template parameter pack have other trailing arguments?

女生的网名这么多〃 提交于 2019-12-23 16:45:50

问题


In the C++14 draft standard, [temp.param]/11 says:

If a template-parameter of a primary class template or alias template is a template parameter pack, it shall be the last template-parameter.

If you try compiling the following template, then the compiler will complain.

template< typename ...Args, void(*f)(Args...) > // ERROR
struct Bar
{};

But how does it work in this case?

template< typename F, F >
struct Bar;

template< typename ...Args, void(*f)(Args...) > // OK ???
struct Bar< void(*)(Args...), f >
{};

I can see that it has something to do with it being part of the specialization class template, but why?

The rule clearly states that it applies to a primary class template. Does this mean that the rules change for specializations?

I tried to search for this in the standard, but couldn't find anything. Can you please shine some light into this.


回答1:


The rule clearly states that it applies to a primary class template. Does this mean that the rules change for specializations?

Yes. Quite simply because a specialization is not a primary class template. So if the wording was intended to apply to all template declarations, it would say so. Instead, the rule is very much intended to only apply to the primary class template (... and alias templates, which cannot be specialized). There is no such restriction for specializations.

This is fundamentally because it is not possible to provide any template arguments after a template parameter pack in the primary template, but it is definitely possible to do so in specializations. For instance, here's one way to concatenate two tuple specializations:

template <typename T, typename U>
struct tuple_concat;

template <typename... Ts, typename... Us> // <== parameter pack *after* parameter pack
struct tuple_concat<tuple<Ts...>, tuple<Us...>> {
    using type = tuple<Ts..., Us...>;
};

This is fine, it works, it's useful. But there's no benefit from being able to write stuff like this in a primary class/variable/alias template - so it's forbidden for simplicity.


As with all things C++, there is of course a footnote. You could have been able to provide a trailing defaulted template parameter that is used to trigger a substitution failure. But there are other ways you can go about solving that problem, and then we'll have Concepts soon anyway.



来源:https://stackoverflow.com/questions/52175224/how-can-a-template-parameter-pack-have-other-trailing-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!