c ++ 11将std :: tuple解压缩为虚拟成员函数

dan*_*man 6 c++ variadic-templates c++11

全文:

我正在尝试构建一个看起来有点像这样的框架:

#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};
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用框架来定义一些可以模拟的外观简单的类.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后建立这些可模拟家庭的多元化......

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 Code Online (Sandbox Code Playgroud)

最后,我们谈到了这一点:我们希望能够编写一个与家庭类型无关的功能,但仍然可以调用run模拟:

void play_simulation(simulation_base& some_household){
     // do some general stuff...

     some_household.run();  
}
Run Code Online (Sandbox Code Playgroud)

总结: run调用虚拟方法的相关模板化实例execute_simulation_wrapped,然后将其解包stored_inputs并将它们提供给simulation具有每个家庭的定制实现的虚拟功能.


我认为我应该问的问题是:

所以,我认为我已经完成了以上大部分设置,但我已经看了很长时间了,我仍然无法确定simulation_wrapper::execute_simulation_wrapped函数如何调用simulation并提供解压缩的元组stored_inputs作为参数包.

我知道有一些问题和博客可以提供有关如何使用解压缩的元组调用常规函数的详细信息,但我还没有设法将其扩展到成员函数,特别是虚拟成员函数.

TMP对我来说是新的,并且仍然完全令人困惑,因此非常感谢相当明确的答案!

Pio*_*cki 7

这通常是在以下帮助下完成的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;};
};
Run Code Online (Sandbox Code Playgroud)

如果你需要一个仅在C++ 14之后index_sequence可用的<utility>,你可以使用以下实现:

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;
Run Code Online (Sandbox Code Playgroud)

DEMO

  • 注意`std :: make_index_sequence <sizeof ...(Ts)>`可以用它的别名`std :: index_sequence_for <Ts ...>`代替. (3认同)