c++ Clang与G++在类模板参数数量和模板模板参数重新声明方面存在分歧

8ulbf1ek  于 2023-03-14  发布在  其他
关注(0)|答案(1)|浏览(118)

在下面的示例中,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++的输出如下:

铿锵:

错误:类模板部分专用化未专用化任何模板参数;

G++

好的
因此,我决定使用clang友好的方法,并在Abstract的声明中添加了第三个参数。

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

现在,Clang和G++对此都很满意,我猜Clang抱怨的原因,是因为专门化并没有专门化任何东西,但那不是真的,它专门化了参数的数量。
接下来,我为template参数添加了另一个特殊化,示例如下:

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++的输出如下:

铿锵:

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

**G++:**一个三个

OK -(声明中也不需要第三个参数)
我不认为Clang就在这里,因为第三个特殊化对template参数有效,而variadic template参数允许我特殊化任意数量的参数,但是我不确定。

**问题:**哪个编译器是有缺陷的?为什么?如果能从规范中引用一句话,让这个问题更清晰,那就太好了。

jdzmm42g

jdzmm42g1#

正如在评论中指出的,问题的第一部分--即是否允许专门化主模板中的可变参数模板参数--本质上与this other question相同,如果您阅读了我对该问题的回答,它包含了部分专门化的偏序规则如何工作的摘要,特别是在您的情况下,问题是从C17开始,template<bool,typename ...> class参数可以接受template<bool> class参数,* 反之亦然 *;这意味着在C17和更高版本中,偏序规则得出的结论是,您编写的部分特化并不比主模板更特化,这使得程序是病态的。
(FWIW,Godbolt上提供的Clang trunk的最新版本接受了这种专门化,我希望CWG 2398最终能够以一种使此代码格式良好的方式得到解决。)
至于你问题的第二部分,关于这对部分专业化:

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>
{};

某些版本的《铿锵》声称第二个是对第一个的“重新声明”,这完全是无稽之谈;这可能是这些版本中的一个bug。2这个问题在 Backbone.js 中得到了修复。

相关问题