生成器用于提升::融合::使用不可复制的值类型进行映射初始化



>我想创建一个能够包含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::mapctor,一切正常。使用生成器会导致编译,指出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::vectorfusion::repetitive_view中使用的实例变得不可复制......因此不可能产生。如何生成 Nsocket_t个实例并将其转发到fusion::map

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

最新更新