嵌套类

时间:2016-04-17 20:29:27

标签: c++ variadic-templates

我正在尝试使用可变参数模板并遇到一个奇怪的问题,我不明白为什么会出现错误消息。

template<int v0, int ...Vs>
class Foo
{
public:
    template<typename nested = void,
        typename = void>
    class Reduce
    {
    public:
        static int const value = v0;
    };

    template<typename nested>
    class Reduce<nested,
        typename std::enable_if<0<sizeof...(Vs)>::type>
    {
    public:
        static int const value = v0 + Foo<Vs...>::template Reduce<>::value;
    };
};

此代码带来错误消息

//example code
int s = Foo<0,1,2,3,4,5>::Reduce<>::value;
std::cout << s << std::endl;

error: incomplete type 'F<5>::Reduce<>' used in nested name specifier

我插入了嵌套的虚拟模板参数,因为模板类中的嵌套模板类不能完全专门化。实际上我不明白为什么编译器会抱怨类型不完整 当我将可变参数更改为

template<int v0, int ...Vs>
class Reduced
{
public:
    static int const value = v0 + Reduce<Vs...>::value;
};

template<int v0>
class Reduced<v0>
{
public:
    static int const value = v0;
};

template<int v0, int ...Vs>
class Foo
{
public:
    class Reduce
    {
    public:
        static int const value = Reduced<v0, Vs...>::value;
    };
};

它有效,但我不知道为什么另一个没有。知道为什么编译器会抛出那个错误吗?谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

typename std::enable_if<0<sizeof...(Vs)>::type

你需要将不平等检查包括在parens中。

typename std::enable_if< (0 < sizeof...(Vs)) >::type

答案 1 :(得分:1)

这归功于C ++标准的引用§14.7.3/ p16显式特化[temp.expl.spec] (强调我的):

  

在类的成员的显式专门化声明中   模板或出现在命名空间范围内的成员模板   成员模板及其一些封闭的类模板可能会保留   unspecialized,,但声明不得明确   如果它包含类模板,则专门化一个类成员模板   也没有明确的专业。

也就是说,你不能拥有专门类型Foo<int...>::Reduced<>的对象,除非Foo封闭类也是专门的。

您可以通过以下方式修改此内容:

template<int v0, int ...Vs>
class Foo {
public:
  class Reduce {
  public:
    static int const value = v0 + Foo<Vs...>::Reduce::value;
  };
};

template<int v0>
class Foo<v0> {
public:
  class Reduce {
  public:
    static int const value = v0;
  };
};

Live Demo

或者你可以摆脱嵌套类:

template<int v0, int ...Vs>
class Foo {
public:
  static int const value = v0 + Foo<Vs...>::value;
};

template<int v0>
class Foo<v0> {
public:
  static int const value = v0;
};

Live Demo

C ++ 17引入了折叠表达式。使用folds表达式,您只需执行以下操作即可执行以下操作:

template<int v0, int ...Vs>
class Foo {
public:
  static const int s = v0 + (Vs + ...);
};

Live Demo