标签:c language-lawyer templates clang template-specialization
考虑以下程序:
template<template<typename ...> class>
struct foo {};
template<template<typename> class C>
struct foo<C> {};
int main() {}
Clang拒绝了它的错误:
class template partial specialization does not specialize any template argument
即使在最新的clang 7.0 HEAD中,请参见demo here.但是,gcc accepts it.
请参阅[temp.class.spec],其中说明了部分特化规则,我找不到任何禁止该模板部分特化的内容.特别是,专业化确实是more specialized,错误消息看起来不正确.
编辑:
但是,gcc的行为也是异常的,请考虑以下程序:
#include <iostream>
template<template<typename ...> class>
struct foo { void show() { std::cout << "Primary.\n"; } };
template<template<typename> class C>
struct foo<C> { void show() { std::cout << "Specialized.\n"; } };
template<class...> struct bar {};
int main() {
foo<bar> f;
f.show();
}
事实证明,gcc在这种情况下使用专用版本,见here.
现在我想问:
>这种标准允许的部分专业化吗?
>哪个编译器是正确的? (一个/全部/没有?)
解决方法:
这个最终似乎是在执行新的C模板模板参数推断partial support for this feature时的GCC错误.
要确定部分特化是否比类模板更专业化,partial ordering is applied to 2 corresponding synthetized functions:
//template class:
template<template<class...>class P> void f_foo0(foo<P>);
//Partial specialization
template<template<class P> class P> void f_foo_partial0(foo<P>);
然后尝试通过使用与其他函数参数对应的参数调用每个函数来执行模板参数推导(参见[temp.func.order])
template<class P> struct Atype{};
template<class ...P> struct ATypePack{};
//Is f_foo_partial at least as specialized as f_foo?
f_foo(foo<AType>{});
//Is f_foo at least as specialized as f_foo_partial?
f_foo_partial(foo<ATypePack>{});
如果模板参数成功(1),则f_foo_partial至少与f_foo一样专用.如果模板参数成功(2),则f_foo至少与f_foo_partial一样专用.(见[temp.deduct.partial]).然后,如果只有一个至少与另一个一样专业,那么它就是更专业的那个.
因此to check if template argument is deductible,然后deduction of template argument from a type正在执行.
然后,要执行此匹配,应用C17中引入的规则[temp.arg.template]/3:
A template-argument matches a template template-parameter P when P is at least as specialized as the template-argument A.[…]
并且[temp.arg.template] / 4指定使用这些发明的两个函数将与前面的情况类似地执行此排序:
template<class...> struct X{};
//for the argument
template<class...P> void f_targ(X<P...>);
//Partial specialization
template<class P> void f_tparam(X<P>);
struct Atype{};
struct ATypePack{};
//Is template template parameter at least as specialized template template arg?
f_targ(X<AType>{});
//Is template template arg at least as specialized as template template parameter?
f_tparam(X<ATypePack>{});
> for(1)模板参数成功推导出… P“ isAType`的参数.
> for(2)有一个特殊规则,仅适用于模板部分排序[temp.deduct.type] /9.2的情况:
[…] During partial ordering, if Ai was originally a pack expansion:
if P does not contain a template argument corresponding to Ai then Ai
is ignored;otherwise, if Pi is not a pack expansion, template argument deduction fails.
这里Ai是ATypePack,Pi是模板< class P>的函数参数中的P. void p_foo_partial(foo< P>).
因此,由于粗体引用的这个规则,模板参数推导失败了(2),因此模板模板参数“class P”比其参数更专业.因此,调用f_foo_partial(foo< ATypePack> {})格式正确.
另一方面,相同的规则,由于[temp.arg.temp] / 3,对f_foo(AType {})的调用很好地形成:
[…] If P contains a parameter pack, then A also matches P if each of A’s template parameters matches the corresponding template parameter in the template-parameter-list of P.[…]
所以f_foo_partial并不比f_foo更专业,所以模板< class< class> C类> struct foo< C> ;;不是模板foo的部分特化.
标签:c,language-lawyer,templates,clang,template-specialization 来源: https://codeday.me/bug/20191004/1854273.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。