C++ boost::fusion::map初始化的生成器,具有不可复制的值类型

C++ boost::fusion::map初始化的生成器,具有不可复制的值类型,c++,boost,metaprogramming,fusion,C++,Boost,Metaprogramming,Fusion,我想创建一个能够包含N个套接字的基类。这些是ZeroMQ套接字,不可复制。在这种情况下,基类一般可以在托管套接字和其他服务函数上实现关闭行为。而派生类可以使用标记类型访问所需的套接字 我的想法是使用boost::fusion::map。套接字类型不是默认的可构造类型,因此我需要作为参数传递:引用上下文和标识套接字类型的int(ZMQ{Socket\u type},即int)。最后,应该有一个生成器函数来创建要放置在fusion::map中的套接字。其思想是立即使用fusion::repeativ

我想创建一个能够包含N个套接字的基类。这些是ZeroMQ套接字,不可复制。在这种情况下,基类一般可以在托管套接字和其他服务函数上实现关闭行为。而派生类可以使用标记类型访问所需的套接字

我的想法是使用
boost::fusion::map
。套接字类型不是默认的可构造类型,因此我需要作为参数传递:引用上下文和标识套接字类型的int(
ZMQ{Socket\u type}
,即
int
)。最后,应该有一个生成器函数来创建要放置在
fusion::map
中的
套接字。其思想是立即使用
fusion::repeative_view
,因为套接字具有所有相同的初始化参数

现在的问题是:如果我手动将
socket{context,int},socket{context,int}
实例传递给
fusion::map
ctor,一切正常。使用生成器会导致编译,说明
socket\t
不可复制

下面是我试图编译的简化代码:

#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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
名称空间mpl=boost::mpl;
名称空间fus=boost::fusion;
结构上下文\u t:boost::不可复制
{};
结构套接字\u t:boost::不可复制
{
socket_t(context_t&context,int-type):context_{&context},type_{type}
{}
socket_t(socket_t&&s):上下文{s.context},类型{s.type}
{}
套接字和运算符=(套接字和运算符)
{
上下文=s.context;
类型=s.type;
归还*这个;
}
void use_fields()常量
{//只是为了避免出现未使用字段的警告
(无效)背景信息;
(无效)类型;
}
私人:
上下文\u t*上下文\u;
int型;
};
//我们需要结合上下文查看键
模板
自动无限上下文(fus::vector v)
{
返回fus::重复_视图{v};
}
模板
结构基类型
{
typedef fus::标记了地图的地图;
base_type():上下文{}//,套接字{}
{}
上下文\u t上下文\u;
//fus::映射套接字;
};
结构tag1{};
结构tag2{};
int main(int argc,char*argv[])
{
语境;
类型定义基本类型测试类型;
autog=infinite_context(fus::make_vector([&c]()->socket_{return{c,1};}));
test_me_type::taged_map m1{socket_t{c,1},socket_t{c,1};//确定
//test_me_type::tagged_map m2{g};//错误:访问已删除的副本!
(b)g;
(无效)m1;
//(空)m2;
返回0;
}
我的问题是,
fusion::vector
fusion::repeative_view
中使用的实例变得不可复制。。。因此,不可能产生新的一代。如何生成N
socket\u t
实例并将其转发到
fusion::map

确定

关键是引入一个可复制的代理对象,该对象具有到
fusion::pair
的隐式转换运算符。缺少的代码段是:

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;
}
struct可转换
{
可转换(上下文测试与控制,内部测试)
:c{&c}
,t{t}
{}
模板
运算符fus::pair()常量
{
返回套接字{*c{,t};
}
私人:
上下文_t*c;
int t_;
};
int main(int argc,char*argv[])
{
语境;
类型定义基本类型测试类型;
autog=infinite_上下文(fus::make_向量(可转换{c,1}));
test_me_type::taged_map m1{socket_t{c,1},socket_t{c,1};//确定
test_me_type::tagged_map m2{g};//也可以!
(b)g;
(无效)m1;
(空)m2;
返回0;
}

声明
自动无限_上下文(fus::vector v)
需要复制向量。将其更改为
自动无限上下文(fus::vector&v)
会有帮助吗?不幸的是,不会。我现在也在这条路径上,试图使用隐式
运算符套接字()引入代理对象。因此,它总是按需生成一个新的r值,但可以复制到其最终目的地,并且仍然有错误归咎于复制构造。是的,我猜通过值返回的函数的结果仍然需要一个可用的复制构造函数(尽管通常会有RVO)。也许还可以看看
boost::ref
,也许在这里会有所帮助。