【发布时间】:2012-07-27 12:49:26
【问题描述】:
X:我想做的事:
我有以下类型:BaseType 和 DerivedType<int k>(参见下面的代码),我需要处理派生类型 std::vector<DerivedType<k>>、k = 1...K 的 K 向量的集合。我想访问这些向量中的对象,并对它们执行依赖于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
派生类型的每个向量都包含O(10^6) 到O(10^9) 对象。最内层的循环是我的应用程序中最耗时的部分,因此使 dynamic_cast 仅作为最外层循环的一个选项。
Y:我尝试过的事情都没有成功。
我目前正在研究 Abrahams C++ Template Metaprogramming 这本书,看看我是否可以使用boost::mpl。我也在boost::fusion 上做教程,看看我是否也可以使用它。然而,这些库的学习曲线相当大,所以我想在我投入一周的时间之前先问一下,什么时候有更好、更简单的解决方案可用。
我的第一次尝试是包装我的向量std::vector<DerivedType<k>>,这样我就可以创建一个vector<WrappedDerivedTypes*>,并在for_each 循环中分别访问每个单个向量。但是,在循环中,我有一系列无法消除的if(dynamic_cast<std::vector<DerivedType<0>>>(WrappedVector) != 0 ){ do for_each loop for the derived objects } else if( dynamic_cast...) { do...} ...。
【问题讨论】:
-
你的
doSomething函数可以引用BaseType吗?您展示的实现不依赖于k模板参数。 -
进一步了解 quamrana 的建议:为什么不直接将
doSomething()设为虚拟方法,并为每个派生类型明确专门化它?然后,您可以将您的 k 个向量存储在指向BaseType的向量的向量中。 (最初,您需要一个“工厂方法”来构造每个DerivedType<k>对象,但此后可以通过父BaseType类型统一处理它们。)就目前而言,我看不出通过制作 @987654348 可以获得什么@派生自BaseType。
标签: c++ generics boost metaprogramming