【问题标题】:Specializing a variadic template template parameter on the minimum number of arguments: legal or not?将可变参数模板模板参数专门用于最小数量的参数:合法与否?
【发布时间】:2012-04-04 01:29:14
【问题描述】:

我有代码:

#include <cstdio>

template<template<typename...> class>
struct Foo 
{ 
    enum { n = 77 };
};

template<template<typename, typename...> class C>
struct Foo<C>
{
    enum { n = 99 }; 
};

template<typename...> struct A { };

template<typename, typename...> struct B { };

int main(int, char**)
{
    printf("%d\n", Foo<A>::n);
    printf("%d\n", Foo<B>::n);
}

这个想法是template&lt;typename, typename...&gt; classtemplate&lt;typename...&gt; class 的一个子集,因此可能可以专门研究它。但它非常深奥,所以也许不是。让我们试试看。

GCC 4.7 说:

$ g++ -std=c++11 test157.cpp 

编译好了!

运行它:

$ ./a.out 
77
99

有效!

Clang 3.1 说:

$ clang++ -std=c++11 test157.cpp
test157.cpp:10:8: error: class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list
struct Foo<C>
       ^  ~~~
test157.cpp:9:10: error: too many template parameters in template template parameter redeclaration
template<template<typename, typename...> class C>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test157.cpp:3:10: note: previous template template parameter is here
template<template<typename...> class>
         ^~~~~~~~~~~~~~~~~~~~~
2 errors generated.

谁是对的?

【问题讨论】:

    标签: c++ templates c++11 template-specialization variadic-templates


    【解决方案1】:

    Clang 拒绝部分特化是错误的。要知道如何解释错误消息,您需要了解 clang 诊断的内容。这意味着诊断一个部分特化,其参数与主类模板的隐式参数列表完全匹配 (&lt;param1, param2, ... , paramN&gt;)。

    但是参数列表不同,所以 clang 不会诊断它。特别是,这与偏特化是否匹配或多或少的参数无关。考虑

    template<typename A, typename B> class C;
    template<typename B, typename A> class C<A, B> {};
    

    这里的部分特化匹配所有内容,而不是主模板匹配的更多内容。并且两个模板的参数列表是不同的,所以这个部分特化是有效的,就像你的一样。

    【讨论】:

    • 谢谢。迷人的例子。考虑到这一点,我的示例只是将可变参数模板模板参数专门用于任何更具体数量的参数(例如,两个)的一般示例。如果我尝试将Foo 专门化为template&lt;typename, typename&gt; class,我会得到相同的行为:GCC 接受,Clang 拒绝。我将提交一个错误(如果尚未完成)。如果不是太麻烦的话,引用标准会让我很高兴。
    【解决方案2】:
    `template<template<typename, typename...> class C> 
    

    并不比

    更专业
    template<template<typename...> class>
    

    它们都采用未知类型参数的列表。只是前者将此列表的一个成员作为不同的参数。 它不包含有关类型的其他信息,因此编译器应该选择一个而不是另一个。

    在可变参数模板的典型用法中,这种特化是根据参数计数生成的。在运行时将可变参数模板视为递归函数,您应该只提供终止条件(作为仅采用一种未知类型的类)。

    Clang 非常热衷于诊断,所以我认为它正在捕捉异常并正确地给出错误。 GCC 能够编译它很奇怪。可能是因为您在struct Astruct B 中分别明确指定要使用哪些模板,gcc 能够捕捉到并抑制异常。

    【讨论】:

    • 有区别。其中一个匹配“具有零个或多个类型名参数的类模板”,另一个匹配“具有一个或多个类型名参数的类模板”。实际上,如果您尝试将template&lt;typename...&gt; struct A { } 作为模板参数传递,其中参数类型为template&lt;typename, typename...&gt; class,Clang 和GCC 都会拒绝它。当然,这并不意味着语言标准也允许基于这种区别进行专业化。如果您提供引用,我很乐意接受。
    • 换一种说法,如果可以根据参数的数量在它们处于积极位置时进行专业化——template&lt;typename...&gt;template&lt;typename, typename...&gt;——我认为没有理论上的障碍也允许当他们处于不利位置时,template&lt;template&lt;typename...&gt; class&gt;template&lt;template&lt;typename, typename...&gt; class&gt;。我不确定的是 ISO 标准是否对此做出了规定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2016-10-12
    • 1970-01-01
    相关资源
    最近更新 更多