2017-06-10 8 views
2

Nソケットを含むことができる基本クラスを作成したいと思います。これらはZeroMQソケットであり、コピー可能ではありません。この場合、基本クラスは管理対象ソケットやその他のサービス関数でシャットダウン動作を一般的に実装できます。派生クラスは、タグタイプを使用して必要なソケットにアクセスできます。boost :: fusion :: mapの初期化でコピー不可能な値の型を使用する

私の考えはboost::fusion::mapでした。ソケット型はデフォルトで構成可能ではないので、ソケット型を識別するコンテキストとintへの参照(ZMQ_{SOCKET_TYPE}int)をパラメータとして渡す必要があります。最後に、fusion::mapに配置するsocket_tを作成するジェネレータ関数が必要です。アイデアはソケットがすべて同じ初期化パラメータを持つので、fusion::repetitive_viewを今使用することです。

問題は、私が手作業でsocket_t{context, int}, socket_t{context, int}インスタンスをfusion::mapに渡すとすべて正常に機能します。ジェネレータを使用すると、socket_tがコピーできないことを示すコンパイルが行われます。 IMOの問題は、このように無世代の可能性... fusion::repetitive_viewで使用fusion::vectorインスタンスがコピー可能でないとなり、ということである

#include <boost/mpl/transform.hpp> 
#include <boost/fusion/include/pair.hpp> 

#include <boost/fusion/include/map.hpp> 
#include <boost/fusion/container/generation/make_vector.hpp> 


using namespace std; 
namespace mpl = boost::mpl; 
namespace fus = boost::fusion; 

struct context_t : boost::noncopyable 
{}; 

struct socket_t : boost::noncopyable 
{ 
    socket_t(context_t& context, int type) : context_{&context}, type_{type} 
    {} 

    socket_t(socket_t&& s) : context_{s.context_}, type_{s.type_} 
    {} 

    socket_t& operator=(socket_t&& s) 
    { 
    context_ = s.context_; 
    type_ = s.type_; 
    return *this; 
    } 

    void use_fields()const 
    { // just to avoid warnings that fields are not used 
    (void)context_; 
    (void)type_; 
    } 

private: 
    context_t* context_; 
    int type_; 
}; 

// we need a view of keys in conjunction with the context 
template<class T> 
auto infinite_context(fus::vector<T> v) 
{ 
    return fus::repetitive_view<fus::vector<T>>{v}; 
} 


template<class... Pairs> 
struct base_type 
{ 
    typedef fus::map<Pairs...> tagged_map; 

    base_type() : context_{} //, sockets_{} 
    {} 

    context_t context_; 
    //fus::map<Pairs...> sockets_; 
}; 

struct tag1 {}; 
struct tag2 {}; 


int main(int argc, char* argv[]) 
{ 
    context_t c; 

    typedef base_type<fus::pair<tag1, socket_t>, fus::pair<tag2, socket_t>> test_me_type; 


    auto g = infinite_context(fus::make_vector([&c]()->socket_t{ return {c, 1}; })); 

    test_me_type::tagged_map m1{socket_t{c, 1}, socket_t{c, 1}}; //OK 
    //test_me_type::tagged_map m2{g}; //Error: access to deleted copy ctor! 

    (void)g; 
    (void)m1; 
    //(void)m2; 

    return 0; 
} 

は、ここで私がコンパイルしようとしている単純化されたコードです。 N socket_tインスタンスを生成してfusion::mapに転送するにはどうすればよいですか?

+1

宣言 '自動infinite_context(FUS ::ベクトル V)'ベクトルをコピーするために必要となります。それを 'auto infinite_context(fus :: vector &v)'に変更するのに役立つでしょうか? – axalis

+0

残念ながら、私は暗黙の 'operator socket_t();'を使ってプロキシオブジェクトを導入しようとしています。そのため、常に新しいr値のオンデマンドを生成しますが、最終的なコピー先までコピーしてもコピー作成を責めにしてエラーを残すことができます。 – ovanes

+0

はい、私は、値によって返された関数の結果はコピーコンストラクタが利用可能であることを要求していると思います(通常はRVOが配置されます)。多分 'boost :: ref'を見てみてください。多分ここで助けてくれるかもしれません。 – axalis

答えて

2

OK解決済みです。

キーは暗黙の変換演算子を持つコピー可能なプロキシオブジェクトをfusion::pair<TagType, socket_t>に導入することでした。行方不明の抜粋です:

struct convertible 
{ 
    convertible(context_t& c, int t) 
    : c_{&c} 
    , t_{t} 
    {} 

    template<class Tag> 
    operator fus::pair<Tag, socket_t>()const 
    { 
    return socket_t{*c_, t_}; 
    } 

private: 
    context_t* c_; 
    int t_; 
}; 

int main(int argc, char* argv[]) 
{ 
    context_t c; 

    typedef base_type<fus::pair<tag1, socket_t>, fus::pair<tag2, socket_t>> test_me_type; 

    auto g = infinite_context(fus::make_vector(convertible{c, 1})); 

    test_me_type::tagged_map m1{socket_t{c, 1}, socket_t{c, 1}}; //OK 
    test_me_type::tagged_map m2{g}; //OK as well! 


    (void)g; 
    (void)m1; 
    (void)m2; 

    return 0; 
}