clang vs g 在类模板上不同意参数和模板模板参数重新分支

Clang vs G++ disagree on class template number of arguments and template template parameter redeclaration

本文关键字:参数 新分支 分支 不同意 vs clang      更新时间:2023-10-16

在以下示例中, Abstract是一个类模板,其第一个参数是类型,第二个参数是另一个模板,将BOOL与任何数量的ARGS一起使用。

template<bool,typename>
struct Default;
template< typename T = void,
          template<bool,typename ...> class = Default>
struct Abstract;
template<typename T>
struct Abstract<T>
{};
template<typename T, template<bool> class C>
struct Abstract<T,C> : Abstract<T>
{};
int main()
{}

Clang和C 的输出如下:

clang: http://rextester.com/bjsw46677

错误:类模板部分专业化并不专业 模板参数;

g http://rextester.com/mdn65674

确定

所以,我决定对Abstract的声明中的第三个参数添加。

template< typename T = void,
          template<bool,typename ...> class = Default,
          typename = void >
struct Abstract;

现在,clang和g 都很好。我猜Clang抱怨的原因是因为专业并没有真正专业。但这不是真的。它专门用于参数数量。

接下来,我为模板模板参数添加了另一个专业化。该示例看起来像这样:

template<bool,typename>
struct Default;
template< typename T = void,
          template<bool,typename ...> class = Default,
          typename = void >
struct Abstract;
template<typename T>
struct Abstract<T>
{};
template<typename T, template<bool> class C>
struct Abstract<T,C> : Abstract<T>
{};
template<typename T, template<bool,typename> class G>
struct Abstract<T,G> : Abstract<T>
{};
int main()
{}

Clang和C 的输出如下:

clang: http://rextester.com/ljioc38789

错误:Abstract<type-parameter-0-0, C, void>的重新定义注意:上一个定义是struct Abstract<T,C> : Abstract<T>

g : http://rextester.com/tsdrz44717

ok-(也不需要声明中的第三个参数(

i 不要以为clang在这里就在这里,因为第三个专业化对于模板模板参数有效,而variadic模板参数允许我专门针对任何数量的参数。但是,我不确定。

问题:哪个编译器是错误的?为什么?从规格中获取报价并对该主题更加清晰真的很高兴。

正如评论中指出的,问题的第一部分(即,是否允许它专业地专业地使用主模板中的variadic模板的模板模板参数 - 本质上是与另一个问题相同。如果您阅读了我对这个问题的回答,它包含了部分订购规则的部分专业化的摘要。特别是在您的情况下,问题是,由于C 17,template<bool,typename ...> class参数可以接受template<bool> class参数,而 vice vice vices ;这意味着,在C 17及以后,部分订购规则得出的结论是,您所写的部分专业化不是比主要模板更专业的部分专业化,这使该程序不构建。<<<<<<<<<<<<<<

(FWIW,Godbolt上可用的Clang Trunk的最新版本接受了专业化,我希望CWG2398最终以使该代码形成良好的方式解决。(

(

至于问题的第二部分,关于一对部分专业:

template<typename T, template<bool> class C>
struct Abstract<T,C> : Abstract<T>
{};
template<typename T, template<bool,typename> class G>
struct Abstract<T,G> : Abstract<T>
{};

某些版本的声称第二个版本是"重新宣传"。第一个只是胡说八道。在这些版本中,这大概是一个错误。这是固定在中继的。