C ++可变资源模板阵列/访问元素

时间:2014-01-06 11:14:21

标签: c++ arrays templates element variadic-templates

在C ++中,我如何能够像数组一样访问可变参数模板的元素?我已经做了一个基本的尝试来展示我试图在下面实现的目标,但是,当然,它不会编译:

template<class... Args> struct Apple{
public:
    Apple(Args... A) : V(A){}
    Apple() : p(0){}
    void push_back(decltype(V[p]) v){
        V[p++] = v;
    }
private:
    Args... V;
    int p;
};

int main(){
    Apple<int, double> a(5, 6.5);
    Apple<int, double> b;
    b.push_back(5);
    b.push_back(6.5);
}

1 个答案:

答案 0 :(得分:2)

我建议你看一下可变参数模板。 typename... Ts不是数组。因此,您不能指望将Args... v扩展为数组。此外,您将如何使用不同类型的每个元素创建一个数组?

您的要求与std::tuple提供的内容非常相似,您应该看一下它的实现。

看看安德烈给出的this GoingNative 2012 video。这是对可变参数模板的一个很好的介绍。


当使用可变参数模板时,这是我的玩具tuple之一。与C ++ 11 stl提供的内容有些重复,但它无论如何都是玩具。

#include <iostream>
#include <vector>
#include <typeinfo>
#include <type_traits>

using namespace std;

template <typename T, typename... Ts> class MyTuple : public MyTuple<Ts...> {
  using base = MyTuple<Ts...>;

public:
  T elem;

  MyTuple(T v, Ts... vs) : base(vs...), elem(v) {}
};

template <typename T> class MyTuple<T> {
public:
  T elem;

  MyTuple(T v) : elem(v) {}
};

template <int i, typename T, typename... Ts> struct type_of {
  static_assert(i < sizeof...(Ts) + 1, "index out of range");
  typedef typename type_of<i - 1, Ts...>::type type;
};

template <typename T, typename... Ts> struct type_of<0, T, Ts...> {
  typedef T type;
};

template <int i, typename T, typename... Ts>
typename enable_if<i == 0, typename type_of<i, T, Ts...>::type&>::type get(MyTuple<T, Ts...> &t) {
  static_assert(i >= 0, "index out of range");
  static_assert(i < sizeof...(Ts) + 1, "index out of range");

  return t.elem;
}

template <int i, typename T, typename... Ts>
typename enable_if<i != 0, typename type_of<i, T, Ts...>::type&>::type get(MyTuple<T, Ts...> &t) {
  static_assert(i >= 0, "index out of range");
  static_assert(i < sizeof...(Ts) + 1, "index out of range");

  MyTuple<Ts...>& base = t;
  return get<i - 1>(base);
}

int main(int argc, char const *argv[]) {
  cout << typeid(type_of<0, int, char, long>::type).name() << endl;         // print i
  cout << typeid(type_of<1, int, char, long>::type).name() << endl;         // print c
  cout << typeid(type_of<2, int, char, long>::type).name() << endl;         // print l

  MyTuple<int, int> t(0, 1);

  cout << get<0>(t) << endl;
  cout << get<1>(t) << endl;

  return 0;
}