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

标签 c++ templates boost

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

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

问题是我只在运行时知道 Variant 的基础类型。据我所知,我只能使用 which() 方法查询它。

有什么方法可以将 Variant 的基础类型 T 传递给此方法吗? 例如,使用 which() 我确实知道有什么类型,但如何传递它?

switch (m_var.which()) { // Returns an int index of types in the order of passed template classes
    case 0: // This is int
    case 1: // This is std::string
    ...
}
...
Writer.write<???>(m_var); // How to pass the type here?

编辑:如果你知道任何其他方法来达到预期的结果 - 实际上获取 boost::variant 内部变量的地址,从那里复制,请与我分享你的想法

谢谢

最佳答案

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

同样,最重要的是将 memcpy 与非 POD 数据类型一起使用是完全伪造的(因此您不能 将它与 std::string 一起使用。曾经)。

使用仅在运行时已知的类型对 variant 进行操作的方法是使用 boost::static_visitor<>

显然,这里是 main() 的示例,它被改编为接近您想要实现的目标,

Live On Coliru

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

关于c++ - 如何将类模板参数传递给 boost::variant?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27523771/

相关文章:

c++ - boost 是否有可移植的方式来使用 ntohl/htonl/ntohs/htons 类型的函数?

c++ - GCC 4.6.1 的链接问题

c++ - 从断言调用时缺少 llvm-cov 覆盖

java - C++模板化方法

c++ - Matlab编译成C++问题: fatal error C1083: Cannot open include file: 'windows.h'

javascript - 判断emberjs中是否存在模板

C++:纯虚拟类型

boost - 在 C++11 中的 boost::asio 套接字对象上重复 std::move

c++ - 为什么 cmake 不定位 gtest 和 gmock 库?

c++ - Linux 中的 STL 容器和线程(并发写入)