c++ - 使用不可复制值类型进行 boost::fusion::map 初始化的生成器

标签 c++ boost metaprogramming fusion

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

我的想法是使用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 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;
}

IMO 的问题是,fusion::repetitive_view 中使用的 fusion::vector 实例变得不可复制......因此无法生成。如何生成 N 个 socket_t 实例并将其转发到 fusion::map

最佳答案

好的解决了。

关键是引入一个可复制的代理对象,该对象具有隐式转换运算符 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;
}

关于c++ - 使用不可复制值类型进行 boost::fusion::map 初始化的生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44475028/

相关文章:

c++ - 箭头与点语法?

c++ - 单个 VirtualAlloc 分配使用的内存(和其他资源)

c++ - 如何使用 Visual Studio 2013 构建 Boost

c++ - CMake:对 boost 库的 undefined reference

c++ - 懒惰评估(短路)模板条件类型的通用方法

ruby - 顶层定义的方法在哪里?

c++ - 如何在 C/C++ 中对字符串应用掩码?

c++ - boost::gregorian::date 没有 `set-type` 函数?

ruby - 重命名由 gem 添加的方法

c++ - __cplusplus 指令在各种编译器中是如何定义的?