2014-12-18 18 views
6

Câu chuyện đầy đủ:C++ 11 unpack std :: tuple vào hàm thành viên ảo

Tôi đang cố gắng để xây dựng một khuôn khổ mà trông hơi như thế này:

#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}; 
} 

Bây giờ chúng ta có thể sử dụng khung làm việc để xác định một vài lớp học đơn giản nhìn có thể được mô phỏng ..

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; 
    } 
} 

Và sau đó xây dựng một đa vũ trụ của các hộ simulatable ...

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.) 

Cuối cùng, chúng tôi nhận vào vấn đề: chúng tôi muốn để có thể viết một chức năng mà là thuyết bất khả tri của loại hộ gia đình, nhưng vẫn có thể gọi run trên mô phỏng:

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

    some_household.run(); 
} 

Tóm lại:run gọi phiên bản có liên quan của phương pháp ảo execute_simulation_wrapped, sau đó mở gói stored_inputs và cung cấp cho chức năng ảo simulation có chức năng triển khai tùy chỉnh cho từng hộ gia đình.


Các câu hỏi mà tôi nghĩ là tôi nên hỏi:

Vì vậy, tôi nghĩ rằng tôi đã có hầu hết các thiết lập ở trên đúng, nhưng tôi đã nhìn này cho một thời gian dài và tôi vẫn không thể tìm ra cách chức năng simulation_wrapper::execute_simulation_wrapped có thể thực hiện cuộc gọi đến simulation và cung cấp gói giải nén stored_inputs làm gói tham số.

Tôi biết có nhiều câu hỏi và blog ở đó cung cấp thông tin chi tiết về cách gọi hàm thông thường với bộ giải nén, nhưng tôi chưa quản lý được chức năng thành viên và chức năng thành viên ảo cụ thể.

TMP là mới đối với tôi và vẫn hoàn toàn khó hiểu, vì vậy câu trả lời khá rõ ràng sẽ được nhiều người đánh giá cao!

Trả lời

7

này thường được thực hiện với sự giúp đỡ của 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;}; 
}; 

Nếu bạn cần một index_sequence, trong đó có sẵn trong <utility> chỉ từ C++ 14, bạn có thể sử dụng thực hiện dưới đây:

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; 

DEMO

+0

crap thánh nhanh và hữu ích. hãy để tôi xem! ... vâng, tôi đoán đó là những gì tôi đã làm sau. Cảm ơn! –

+0

@ dan-man Tôi đã phải sửa đổi một chút các phần của mã của bạn để làm cho nó compilable, nhưng nó không thay đổi giải pháp chính nó –

+3

Lưu ý rằng 'std :: make_index_sequence ' có thể được thay thế bằng bí danh của nó 'std :: index_sequence_for '. – Jarod42

Các vấn đề liên quan