用于递归继承的具有类型和非类型参数混合的 C++ 可变参数模板

时间:2021-05-22 19:49:43

标签: c++ templates variadic-templates

我想实现这一目标:

Foo<int, 5, double, 7> foo_1;
Foo<char, 7> foo_2;

foo_1.Foo<int>::value[4] = 1;
foo_2.Foo<char>::value[1] = 'x';

(这是一个过于简单的例子,Foo 的作用远不止于此。)

如何使用可变参数模板做到这一点?

TLDR;

我知道如果只使用类型或非类型,可变参数模板可以这样使用:

template <typename ...T>
struct Foo;

template<typename T, typename ...Args>
struct Foo<T, Args...> : Foo<T>, Foo<Args...> {
    Foo(T t, Args... args) : Foo<T>(t), Foo<Args...>(args...) { }
};

template<typename T>
struct Foo<T> {
    T value;

    Foo<T>(T v) : value(v) {}
};

Foo<int, double, char> f(7, 88.1, 'x');
f.Foo<double>::value = 5;

但我不知道是否可以使用可变参数模板配对和混合类型和非类型模板参数。

3 个答案:

答案 0 :(得分:4)

这不可能。您必须满足以下条件之一:

Foo<Bar<int, 5>, Bar<double, 7>> foo_1;
Foo<int, Bar<5>, double, Bar<7>> foo_1;
// ...?

如果值总是整数,你也可以试试这个:

Foo<int[5], double[7]> foo_1;

然后从每个参数中提取元素类型和范围。

答案 1 :(得分:3)

<块引用>

但我不知道是否可以使用可变参数模板配对和混合类型和非类型模板参数。

不使用备用可变参数模板。但是您可以包装多种类型/尺寸。

假设您有一个 Bar 类,如下所示

template <typename T, std::size_t N>
struct Bar
 { std::array<T, N>  value; };

使用类特化,你可以有一个可变参数 Bar 所以一个可变参数列表一个可变参数列表

template <typename...>
struct Foo;

template <typename ... Ts, std::size_t ... Ns>
struct Foo<Bar<Ts, Ns>...> : public Bar<Ts, Ns>...
 { };

您可以按如下方式使用

   Foo<Bar<int, 5>, Bar<double, 7>> foo_1;
   Foo<Bar<char, 7>> foo_2;

   foo_1.Bar<int, 5>::value[4] = 1;
   foo_2.Bar<char, 7>::value[1] = 'x';

下面是一个完整的编译示例

#include <array>

template <typename T, std::size_t N>
struct Bar
 { std::array<T, N>  value; };

template <typename...>
struct Foo;

template <typename ... Ts, std::size_t ... Ns>
struct Foo<Bar<Ts, Ns>...> : public Bar<Ts, Ns>...
 {
 };

int main ()
 {
   Foo<Bar<int, 5>, Bar<double, 7>> foo_1;
   Foo<Bar<char, 7>> foo_2;

   foo_1.Bar<int, 5>::value[4] = 1;
   foo_2.Bar<char, 7>::value[1] = 'x';
 }

答案 2 :(得分:0)

您可以将数组类型作为 typename 传递,例如在您的情况下将变为:

Foo<std::array<int, 5>, std::array<double, 7> > foo_1(
    std::array<int, 5>{0,0,0,0,0},
    std::array<double, 7>{0,0,0,0,0,0,0});

foo_1.Foo<std::array<int, 5>>::value[4] = 1;