【发布时间】:2016-09-25 19:18:28
【问题描述】:
我需要用相当大的类替换代码中的动态多态性,但我遇到了 CRTP + 可变参数模板设计的问题。
为了说明,我在下面提供了一个玩具问题。
有一个动态多态的类,使用如下接口:
int main() {
Loop loop;
Add add ;
loop.set(add);
loop.run();
Sub sub ;
loop.set(sub);
}
当然,Sub 和 Add 派生自基类 Operation 和 op(double & v) 是一个虚方法。
由于其他原因我需要保留这个接口,同时通过静态多态来改变动态,这是我到目前为止的解决方案:
template <typename T> class Operation {
public:
double d=1.;
void op(double & d) { static_cast<T*>(this)->op(d);}
};
class Add final: public Operation<Add> {
public: void op(double & v) { v += d; }
};
class Sub final: public Operation<Sub> {
public: void op(double & v) { v -= d; }
};
对于Loop 类:
template <typename... Types>
class MetaLoop {
public:
double d = 0 ;
template <typename T> void set(T & t) {
std_cxx17::get<std::vector<T*> >(data).push_back(&t) ;
}
template <typename T> void run() {
for (auto j = 0; j<2E9 ; ++j)
std_cxx17::get<std::vector<T*> >(data).back()->op(d);
std::cout << d << std::endl;
}
private:
std::tuple<std::vector<Types*>... > data ;
};
typedef MetaLoop<Add,Sub> Loop ;
std_cxx17::get<T*>(data) 是对按类型选择元组中元素的方法的调用,类似于this post
然而,这个解决方案几乎需要我想要的接口,除了需要向run() 提供模板参数,即run<Add> 和run<Sub> 以及需要注册 Add 和 Sub 到 MetaLoop 在 typedef MetaLoop<Add,Sub> Loop
我想知道是否可以在不使用宏的情况下:
- 自动将
Operation<T>类注册到MetaLoop(即自动调用typedef Metaloop<...operations...>) - 避免将模板类提供给
run方法。 (即致电run()而不是run<Add>()) - 从库中获取此方法:是否有库(例如 Boost)可以静态提供这种多态性?
请记住,我知道我可以使用其他几种架构,但我必须使用许多其他限制。这只是一个用来举例说明的玩具问题。
提前致谢!
编辑 1:
问题 2 已回答!见这里:http://coliru.stacked-crooked.com/a/e68ea7faabba3e40
【问题讨论】:
-
如果您不明确指定
Add,您希望它运行什么?是否应该同时运行Add和Sub? -
我希望它运行已设置的最后一个类型。谢谢!
-
那么,您希望每次只有一个活动类型吗?为什么要将所有内容都存储在向量中?
-
好问题!谢谢回答!我将所有内容存储在一个向量中,因为我希望存储多个
Add的实例。 -
好的,但是如果您关心的是永远只使用最后一个,为什么还要跟踪其他的呢?你不能简单地替换活动的吗? (我要求能够给你一个正确的答案)。
标签: c++ boost polymorphism tuples crtp