c++ - 管理模板派生类型的 vector 集合

标签 c++ generics boost metaprogramming

X:我想做什么:

我有以下类型:BaseTypeDerivedType<int k> (见下面的代码),我需要处理 K 的集合派生类型的 vector std::vector<DerivedType<k>> , k = 1...K .我想访问这些 vector 中的对象,并根据 k 对它们执行操作。 . K是一个编译时间常数。问题在实现中说明:

类型定义为:

#include <iostream>
#include <algorithm>

struct BaseType { // Interface of the DerivedTypes
  virtual void print(){std::cout << "BaseType!" << std::endl; }
};

template< int k >
struct DerivedType : public BaseType {
  static const int k_ = k;
  // ... function calls templated on k ...
  void print(){std::cout << "DerivedType: " << k_ << std::endl;}
};

template< int k >
void doSomething ( DerivedType<k>& object ) { object.print(); }

我想做的是:

int main() {

  // My collection of vectors of the derived types:
  std::vector<DerivedType<0>> derType0(2);
  std::vector<DerivedType<1>> derType1(1);
  std::vector<DerivedType<2>> derType2(3);
  // ... should go to K: std::vector<DerivedType<K>> derTypeK;

  // Iterate over the derived objects applying a k-dependent templated function:
  std::for_each(begin(derType0),end(derType0),[](DerivedType<0>& object){
    doSomething<0>(object);
  });
  std::for_each(begin(derType1),end(derType1),[](DerivedType<1>& object){
    doSomething<1>(object);
  });
  std::for_each(begin(derType2),end(derType2),[](DerivedType<2>& object){
    doSomething<2>(object);
  });

  return 0;
}

我想避免重复代码,这样我只需要更改 K ,它是 O(10) 的编译时间常量.理想情况下,我会有一些“更像”这样的东西:

// Pseudocode: do not try to compile this

create_derived_objects(DerivedType,K)
  = std::vector< std::vector<DerivedType<k>>* > my_K_derived_types;                                                  

for each vector<DerivedType<k>>* derivedTypes in my my_K_derived_types
  for each object in (*derivedTypes)
    doSomething<k> on object of type derivedType<k>
    // I could also restrict doSomething<k> to the base interface

派生类型的每个 vector 都包含 O(10^6)O(10^9)对象。最内层循环是我的应用程序中最耗时的部分,因此 dynamic_cast 只是最外层循环的一个选项。

Y:我尝试过但没有成功的东西。

我目前正在研究 Abrahams C++ 模板元编程书,看看我是否可以使用 boost::mpl .我也在做关于 boost::fusion 的教程看看我是否也可以使用它。然而,这些库的学习曲线相当大,所以我想在我投入一周的时间之前先问问有没有更好更简单的解决方案。

我的第一个尝试是包装我的载体 std::vector<DerivedType<k>>这样我就可以创建一个 vector<WrappedDerivedTypes*> ,并在 for_each 中分别访问每个单个 vector 环形。但是,在循环中我有一系列 if(dynamic_cast<std::vector<DerivedType<0>>>(WrappedVector) != 0 ){ do for_each loop for the derived objects } else if( dynamic_cast...) { do...} ...我无法消除。

最佳答案

基于 vector 的通用链表的递归解决方案、策略模式和通过链表递归应用策略的东西怎么样? (注意:改进版见文末):

#include <iostream>
#include <vector>

template <int j>
class holder {
public:
    const static int k = j;
};

template <int j>
class strategy {
public:
    void operator()(holder<j> t)
    {
        std::cout << "Strategy " << t.k << std::endl;
    }
};

template <int k>
class lin_vector {
private:
    std::vector<holder<k>> vec;
    lin_vector<k-1> pred;
public:
    lin_vector(const lin_vector<k-1> &pred, std::vector<holder<k>> vec)
        : vec(vec), pred(pred) { }
    std::vector<holder<k>> get_vec() { return vec; }
    lin_vector<k-1> &get_pred() { return pred; }
};

template <>
class lin_vector<0> {
public:
    lin_vector() { }
};

template <int k, template <int> class strategy>
class apply_strategy {
public:
    void operator()(lin_vector<k> lin);
};

template <int k, template <int> class strategy>
void apply_strategy<k, strategy>::operator()(lin_vector<k> lin)
{
    apply_strategy<k-1, strategy>()(lin.get_pred());
    for (auto i : lin.get_vec())
    strategy<k>()(i);
}

template <template <int> class strategy>
class apply_strategy<0, strategy>
{
public:
    void operator()(lin_vector<0> lin) { /* does nothing */ } 
};


template <int k>
lin_vector<k> build_lin()
{
    return lin_vector<k>(build_lin<k-1>(), {holder<k>()});
}

template <>
lin_vector<0> build_lin()
{
    return lin_vector<0>();
}

int main(void)
{
    apply_strategy<5, strategy>()(build_lin<5>());
}

使用 C++11 编译器编译它。 很可能您会发现构建 lin_vector 需要大量复制这一事实并不令人满意,但您可以专门化结构以满足您的需要(也许用 pred 替换指针或将创建策略直接嵌入到链表中)。

编辑:这里有一个改进版本,它避免了大量复制,并以更连贯和统一的方式处理列表构建和处理:

#include <iostream>
#include <vector>

template <int j>
class holder {
public:
    const static int k = j;
};

template <int k>
class lin_vector {
private:
    std::vector<holder<k>> vec;
    lin_vector<k-1> pred;
public:
    std::vector<holder<k>> &get_vec() { return vec; }
    lin_vector<k-1> &get_pred() { return pred; }
};

template <>
class lin_vector<0> {
public:
    lin_vector() { }
};

template <int k, template <int> class strategy>
class apply_strategy {
public:
    void operator()(lin_vector<k> &lin);
};

template <int k, template <int> class strategy>
void apply_strategy<k, strategy>::operator()(lin_vector<k> &lin)
{
    apply_strategy<k-1, strategy>()(lin.get_pred());
    strategy<k>()(lin.get_vec());
}

template <template <int> class strategy>
class apply_strategy<0, strategy>
{
public:
    void operator()(lin_vector<0> &lin) { /* does nothing */ } 
};

template <int j>
class strategy {
public:
    void operator()(std::vector<holder<j>> &t)
    {
        std::cout << "Strategy " << j << ", elements: ";
        for (auto v : t)
            std::cout << v.k << " ";
        std::cout << std::endl;
    }
};

template <int j>
class build_strategy {
public:
    void operator()(std::vector<holder<j>> &t)
    {
        for (unsigned int i = 0; i < j; i++)
            t.push_back(holder<j>());
    }
};

int main(void)
{
    const int K = 5;
    lin_vector<K> list;
    apply_strategy<K, build_strategy>()(list);
    apply_strategy<K, strategy>()(list);
}

关于c++ - 管理模板派生类型的 vector 集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11688113/

相关文章:

c++ - 如何从 c 中的文件中删除记录(保存的记录是 struct )

c++ - 存放高分表,用什么容器?

c++ - 在容器中存储模板化派生类

c++ - 为什么 boost::ptr_list 使用底层 void *?

c++ - Boost::message_queue::receive/send 不适用于最新版本

c++ - 绑定(bind)到私有(private)继承的成员函数

c++ - 如何在 Qt 中实现类似 Google map 的磁贴滚动?

java - 方法具有(意外地)与另一个方法相同的删除

generics - 带有数组的 Swift countElements()

c++ - 将 boost lambda 与复合表达式一起使用