完整故事:
我正在尝试构建一个看起来有点像这样的框架:
#include <tuple>
#include <memory>
using namespace std;
// this class allows user to call "run" without any args
class simulation_base{
public:
int run(){ execute_simulation_wrapped(); };
protected:
virtual int execute_simulation_wrapped(); {return 0;};
}
// this class funnels some stored inputs into a soon-to-be-overridden method
template <typename Ts...>
class simulation_wrapper : public simulation_base {
tuple<shared_ptr<Ts>... > stored_inputs;
public:
int execute_simulation_wrapped() {/* how do you call simulation method? */};
protected:
virtual int simulation(const Ts&...){return 0};
}
现在我们可以使用该框架来定义几个可以模拟的看起来简单的类..
class jones_household : public simulation_wrapper< woman, girl, cat >{
int simulation(woman mrs_jones, girl mary, cat sniffles)
// mrs_jones and her daugther mary play with sniffles the cat
return 1;
}
}
class smith_household : public simulation_wrapper< man, dog >{
int simulation(man mr_smith, dog fido)
// mr_smith and his dog fido go for a walk
return 1;
}
}
然后构建这些可模拟家庭的多元宇宙...
smith_household uinverse_1_smiths;
smith_household uinverse_2_smiths;
jones_houshold uinverse_1_jones;
jones_houshold uinverse_2_jones;
// set the values of the stored_inputs (i.e. fido, sniffles etc.)
最后,我们进入正题:我们希望能够编写一个与家庭类型无关的函数,但仍然能够在模拟中调用run
:
void play_simulation(simulation_base& some_household){
// do some general stuff...
some_household.run();
}
总结: run
调用虚方法 execute_simulation_wrapped
的相关模板实例,然后解压 stored_inputs
并将它们提供给虚拟 simulation
函数,该函数为每个家庭定制实现。
我认为我应该问的问题:
所以,我想我已经正确设置了上面的大部分内容,但是我已经研究了这个很长一段时间,但我仍然无法弄清楚 simulation_wrapper::execute_simulation_wrapped
函数可以调用simulation
并提供解包的元组stored_inputs
作为参数包。
我知道那里有 SO 问题和博客提供了有关如何使用未打包的元组调用常规函数的详细信息,但我还没有设法将其扩展到成员函数,特别是虚拟成员函数。
TMP 对我来说是新手,仍然非常困惑,因此非常感谢能提供相当明确的答案!
最佳答案
这通常是在 index_sequence
的帮助下完成的:
template <typename... Ts>
class simulation_wrapper : public simulation_base
{
tuple<shared_ptr<Ts>... > stored_inputs{new Ts...};
public:
// MAGIC STARTS HERE
int execute_simulation_wrapped() { return execute_simulation_wrapped(std::make_index_sequence<sizeof...(Ts)>{}); }
private:
template <std::size_t... Is>
int execute_simulation_wrapped(std::index_sequence<Is...>) { return simulation(*std::get<Is>(stored_inputs)...); }
// MAGIC ENDS HERE
protected:
virtual int simulation(const Ts&...){return 0;};
};
如果你需要 index_sequence
,可在 <utility>
中找到仅从 C++14 开始,您可以使用以下实现:
template <std::size_t... Is>
struct index_sequence {};
template <std::size_t N, std::size_t... Is>
struct make_index_sequence_h : make_index_sequence_h<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct make_index_sequence_h<0, Is...>
{
using type = index_sequence<Is...>;
};
template <std::size_t N>
using make_index_sequence = typename make_index_sequence_h<N>::type;
关于c++11 将 std::tuple 解压到虚拟成员函数中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27549127/