简体   繁体   English

如何在0可变参数上专门化可变参数模板类?

[英]How do I specialise a variadic template class on 0 variadic arguments?

Suppose I have a class that can take a type and a varadic number of arguments: 假设我有一个类可以采用一个类型和一个varadic数量的参数:

template <typename T, typename... Args>
class B
{
    T<Args...> x;
};

This class forms the basis for an alias type which will look like this: 此类构成了别名类型的基础,如下所示:

template <typename... Args>
using AliasedType = B<T, Args...>;

But there are instances when the type T is not a template, in which case the varadic pack will be of length 0. However, class B will still attempt to declare an instance of this type with an empty set of template arguments, causing an error. 但是有些情况下类型T不是模板,在这种情况下,varadic包的长度为0.但是, class B仍将尝试使用一组空模板参数声明此类型的实例,从而导致错误。 So to get around this, I tried creating a template specialisation of B which takes no varadic arguments at all: 因此,为了解决这个问题,我尝试创建一个B的模板特化,它根本不需要任何varadic参数:

template <typename T>
class B<T>
{
    T x;
};

But this doesn't seem to work. 但这似乎不起作用。

To illustrate the problem in a working example: 为了说明工作示例中的问题:

class A
{
};

template <typename T, typename... Args>
class B
{
    T<Args...> x;
};

template <typename T>
class B<T>
{
    T x;
};

main() {
    B<A> a;
}

The output is: 输出是:

error: ‘T’ is not a template T<Args...> x;

Live example here 这里有实例

Why isn't this resolving to the specialised version that accepts non-template types? 为什么这不能解析为接受非模板类型的专用版本? I'm sure I'm missing something really obvious here... It seems like an empty variadic template pack is not resolved as "nothing" as I had thought. 我确定我错过了一些非常明显的东西......似乎空的可变参数模板包并没有像我想象的那样被解决为“无关紧要”。

Here's an idea. 这是一个想法。 It might not be optimal, but it works. 它可能不是最佳的,但它的工作原理。 First of all, you want your first parameter for B to be a template template parameter (otherwise the error would even appear for valid arguments). 首先,您希望B的第一个参数是模板模板参数(否则错误甚至会出现在有效参数中)。 For a non-template type, you could wrap the type in a template. 对于非模板类型,您可以将类型包装在模板中。 This even works for basic types like double : 这甚至适用于像double这样的基本类型:

template <template<typename...> class T, typename... Args>
class B
{
    T<Args...> x;
};

template <typename T>
struct MakeTemplate {
    template <typename...> using type = T;
};

template <typename T>
class Testclass {
    T datamember;
};

main() {
    B<MakeTemplate<double>::type > b1;
    B<Testclass,int> b2;
}

This compiles fine, as you can see here . 正如你在这里看到的那样编译得很好。 Might this be what you wanted? 这可能是你想要的吗? That said I just want to mention that you only need the whole logic if you need to access the template arguments of the supplied class for some reason besides declaring the member variable x (in B ). 这就是说我只想提一下,除了声明成员变量x (在B )之外,如果由于某种原因需要访问所提供类的模板参数,则只需要整个逻辑。 Otherwise, you could just pass the fully specified class with all parameters filled in, ie B< Testclass<double> > or B<double> in which case B would only need one template argument and that would always be a typename/class and not a template. 否则,您可以只传递填充了所有参数的完全指定的类,即B< Testclass<double> >B<double>在这种情况下, B只需要一个模板参数,并且始终是typename / class而不是一个模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM