可变参数模板和多重继承

gra*_*olf 1 multiple-inheritance variadic-templates c++11

我正在努力使用可变参数模板进行多重继承.

到目前为止这是我的代码:

template <typename U>
    class id_map {
    public:
    std::vector<U> vec_;
};
Run Code Online (Sandbox Code Playgroud)

现在我想初始化另一个类,它从id_map继承多次,如下所示:

template<typename ... T>
class constant_allkey_map : public id_map<T> ... {
private:
public:
    template <typename U>
    void push_back(U i) {
        id_map<U>::vec_.push_back(i);
    }
};
Run Code Online (Sandbox Code Playgroud)

这有效,我可以很好地访问它:

constant_allkey_map<int, long> cakm;
cakm.push_back<int>(1);
Run Code Online (Sandbox Code Playgroud)

当我尝试这样的事情时,它失败了:

constant_allkey_map<int, int> cakm;
Run Code Online (Sandbox Code Playgroud)

有错误

"duplicate base type id_map<int> invalid".
Run Code Online (Sandbox Code Playgroud)

我做了一些阅读,似乎我应该用id参数扩展id_map模板:

template <size_t i_, typename U>
class id_map ...
Run Code Online (Sandbox Code Playgroud)

但我不知道如何在继承部分传递该id:

template<typename ... T>
class constant_allkey_map : public id_map<T> ... {
Run Code Online (Sandbox Code Playgroud)

有人可以帮帮我吗?如果我这样做完全错了,请指出正确的方向?

Tom*_*pen 6

我不认为继承在这里是正确的.因此,我建议采用以下方法来实现您的目标:

#include <tuple>
#include <vector>

template <typename U>
class id_map
{
public:
  typedef U value_type;

public:
  std::vector<U> vec_;
};

template<typename... T>
class constant_allkey_map
{
private:
  typedef std::tuple<id_map<T>...> tuple_t;

public:
  template<
    std::size_t Idx,
    typename U = typename std::tuple_element<Idx, tuple_t>::type::value_type
  >
  void push_back(U x)
  {
    std::get<Idx>(maps_).vec_.push_back(x);
  }

  template<
    std::size_t Idx,
    typename U = typename std::tuple_element<Idx, tuple_t>::type::value_type
  >
  U get(int i) const
  {
    return std::get<Idx>(maps_).vec_[i];
  }

private:
  tuple_t maps_;
};
Run Code Online (Sandbox Code Playgroud)

用法非常简单:

#include <iostream>

int main(int, char**)
{
  constant_allkey_map<int, long> cakm;
  cakm.push_back<0>(1);
  cakm.push_back<0>(3);
  cakm.push_back<1>(2);
  cakm.push_back<1>(4);

  std::cout << cakm.get<0>(0) << std::endl;
  std::cout << cakm.get<1>(0) << std::endl;
  std::cout << cakm.get<0>(1) << std::endl;
  std::cout << cakm.get<1>(1) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例.

基本上你只是std::tuple为你做肮脏的工作.你甚至可以这样做:

template<typename... T>
using constant_allkey_map = std::tuple<std::vector<T>...>;
Run Code Online (Sandbox Code Playgroud)

并直接使用std :: get.