Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将类模板参数传递给boost::variant?_C++_Templates_Boost - Fatal编程技术网

C++ 如何将类模板参数传递给boost::variant?

C++ 如何将类模板参数传递给boost::variant?,c++,templates,boost,C++,Templates,Boost,我有一个使用boost::get of boost:variant模块的模板方法: typedef boost::variant<int, std::string, bool, uint8_t> Variant; template <class T> void write(const Variant& t) { size_t sizeT = boost::apply_visitor(SizeOfVisitor(), t); memcpy(&

我有一个使用boost::get of boost:variant模块的模板方法:

typedef boost::variant<int, std::string, bool, uint8_t> Variant;

template <class T>
void write(const Variant& t) {
    size_t sizeT = boost::apply_visitor(SizeOfVisitor(), t);
    memcpy(&v[offset], &boost::get<T>(t), sizeT);
}
编辑:如果您知道实现所需结果的任何其他方法-实际获取boost::variant内部变量的地址,从那里复制,请与我分享您的想法

谢谢您

开关(m_var.which()){//返回类型的int索引,索引顺序为传递的模板类
switch (m_var.which()) { // Returns an int index of types in the order of passed template classes
    case 0: // This is int
      Writer.write<int>(m_var);
    break;
    case 1: // This is std::string
      Writer.write<std::string>(m_var);
    break;
    ...
}
案例0://这是int Writer.write(m_var); 打破 案例1://这是std::string Writer.write(m_var); 打破 ... }

:)

我碰巧在这里写了一个非常相似的答案:

同样,最重要的是,对非POD数据类型使用
memcpy
完全是假的(因此不能将其与
std::string
一起使用)

对只有在运行时才知道类型的
variant
s进行操作的方法是使用
boost::static\u visitor

下面是一个例子,其中
main()
经过调整,非常接近您想要实现的目标

#包括
#包括
#包括//仅作为示例
#包括
命名空间序列化{
命名空间自定义{
模板
void do_序列化(T const&x,Out&Out)
{
静态断言(boost::is_pod(),“”);
char const*rawp=reinterpret_cast(&x);
标准:复制(rawp,rawp+sizeof(T),输出);
}
模板
void do_序列化(std::string const&x,Out&Out)
{
不序列化(x.size(),out);
用于(自动通道:x)
do_序列化(ch,out);
}
}
结构序列化\u f:public boost::static\u visitor{
模板
void运算符()(boost::variant const&v,Out&Out)const
{
boost::apply_visitor(boost::bind(*this,_1,boost::ref(out)),v);
}
模板
void运算符()(T常量和x,Out和Out)常量
{
使用customization::do_serialize;//ADL分派
dou序列化(x,out);
}
};
模板
输出序列化(T常量和v,输出){
常量静态序列化_f_vis{};
_vis(v,out);
返回;
}
}
名称空间MyUserTypes{
结构A{
std::字符串名;
int i;
};
模板void do_serialize(const&v,Out&Out){//ADL将发现
序列化::序列化(v.name,out);
序列化::序列化(v.i,out);
}
}
int main(){
使用名称空间序列化;
std::矢量二进制数据;
自动输出插入器=返回插入器(二进制数据);
//变体和自定义类型
typedef boost::变量V;
MyUserTypes::A myA{“0123456789”,99};
V=boost::array();
序列化(myA,out\u插入器);
序列化(v,输出插入器);
v=myA;
序列化(v,输出插入器);

std::cout Haha:)这很有趣。但这不是我想写东西的地方。我正在用另一种方法写东西。@rightaway717解决方案是一样的,只需将开关移到你想进行分派的地方。在所有情况下,你都需要运行时分派方法,唯一的改进是有某种map这是将一个值映射到一个类型,比如一个
boost::fusion::map
,但另一方面,我不确定这在理论上是否可行,所以我恐怕这是你能得到的最好的结果:)如果你要提倡切换魔法类型索引,为什么不同时提倡一些goto呢time@sehe这是我想到的最好的,以访客为基础的解决方案可能确实会更好,但也意味着更多的样板代码^^@Drax我很确定,如果他们将使用限制在c++14及以上,这是完全可能的。事实上,您已经可以完成管道设计并获得“多态性”仅使用c++11定义的内联访问者:请参阅。普通代码已经使用lambda中定义的本地结构,以减少命名空间混乱。有一个相关的变化。如果结果类型不匹配,仍然需要进行一些调整。您不能
memcpy
一个
std::string
值。我实际上没有使用它。对于字符串,我有一个单独的方法来memcpy它的内容(mystring.c_str())。我认为这是允许的,对吗?按照你问题中的代码设置方式,你会编写一个函数(错误地)
memcpy
s一个
std::string
应该接收一个
std::string
-保持变量。你能解释一下
boost::如何应用访问者(boost::bind(*this,_1,boost::ref(out)),v);
工作,访问者类的
操作符()
是用T=具体类型(int,float等)调用的。我不明白替换是如何工作的。
bind
函数后没有替换变量。我检查了boost手册,虽然这部分在文档中也不清楚。@rightaway717
apply\u访问者
期望。它使用变量中包含的具体元素值调用该函子。现在,因为我们的函数n需要两个参数,我们将第二个参数绑定到
ref(out)
,因此一元绑定函子仍然与
apply\u visitor
兼容。
switch (m_var.which()) { // Returns an int index of types in the order of passed template classes
    case 0: // This is int
      Writer.write<int>(m_var);
    break;
    case 1: // This is std::string
      Writer.write<std::string>(m_var);
    break;
    ...
}
#include <boost/variant.hpp>
#include <boost/bind.hpp>

#include <boost/array.hpp> // just as a sample
#include <iostream>

namespace serialization {

    namespace customization {
        template<typename T, typename Out, typename R = typename boost::enable_if<boost::is_pod<T>, void>::type>
            void do_serialize(T const& x, Out& out)
            {
                static_assert(boost::is_pod<T>(), "");
                char const* rawp = reinterpret_cast<char const*>(&x);
                std::copy(rawp, rawp+sizeof(T), out);
            }

        template<typename Out>
            void do_serialize(std::string const& x, Out& out)
            {
                do_serialize(x.size(), out);
                for(auto ch : x)
                    do_serialize(ch, out);
            }
    }

    struct serialize_f : public boost::static_visitor<> {
        template<typename Out, typename... T>
            void operator()(boost::variant<T...> const& v, Out& out) const
            {
                boost::apply_visitor(boost::bind(*this, _1, boost::ref(out)), v);
            }

        template<typename T, typename Out>
            void operator()(T const& x, Out& out) const
            {
                using customization::do_serialize; // ADL dispatch
                do_serialize(x, out);
            }
    };

    template <typename T, typename Out>
        Out serialize(T const& v, Out out) {
            const static serialize_f _vis {};
            _vis(v, out);
            return out;
        }

}

namespace MyUserTypes {

    struct A {
        std::string name;
        int i;
    };

    template<typename Out> void do_serialize(A const& v, Out& out) { // ADL will find this
        serialization::serialize(v.name, out);
        serialization::serialize(v.i, out);
    }
}

int main() {
    using namespace serialization;
    std::vector<uint8_t> binary_data;
    auto out_inserter = back_inserter(binary_data);

    // variants and custom types
    typedef boost::variant<MyUserTypes::A, boost::array<char, 42> > V;
    MyUserTypes::A myA { "0123456789", 99 };
    V v = boost::array<char,42>();

    serialize(myA, out_inserter);
    serialize(v, out_inserter);
    v = myA;
    serialize(v, out_inserter);

    std::cout << "Bytes in binary_data vector: " << binary_data.size() << "\n";
}