c++ - boost::recursive_variant 接受 map,但拒绝 unordered_map

标签 c++ boost

您能解释一下为什么这个结构有效吗:

typedef boost::make_recursive_variant<
    boost::blank,
    std::string,
    std::vector< std::string >,
    std::vector< int32_t >,
    std::vector< int64_t >,
    std::vector< double >,
    std::vector< std::complex<double> >,
    std::map< std::string, boost::recursive_variant_ > 
>::type Variant; 

这不会:

typedef boost::make_recursive_variant<
    boost::blank,
    std::string,
    std::vector< std::string >,
    std::vector< int32_t >,
    std::vector< int64_t >,
    std::vector< double >,
    std::vector< std::complex<double> >,
    std::unordered_map< std::string, boost::recursive_variant_ > 
>::type Variant;

不幸的是,我无法理解错误消息。它说了一些关于

  static int initialize(void* dest, param_T operand)
                        ^
/usr/include/boost/variant/detail/initializer.hpp:104:24: note:   no known conversion for argument 2 from ‘const std::unordered_map<std::__cxx11::basic_string<char>, boost::variant<boost::detail::variant::recursive_flag<boost::blank>,

//Skipped 

to ‘boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<8l>,
Ubuntu 16.04,gcc 5.4.0 20160609,boost 1.58。

最佳答案

哈。你随意提到 SWIG 的评论让我的脑海中灵光一闪。

我不会信任 SWIG 任何涉及 boost::[make_recursive_]variant 的事情。既然您提到了这一点,我 99% 都清楚 SWIG 无法理解所涉及的包装器类型。谜团解开了。

好处是,如果您可以使用boost::unordered_map,则不需要它。这是因为由于实现细节,std::unordered_map 可能要求映射类型在(浅)实例化时完整:How to have an unordered_map where the value type is the class it's in? .

Live On Coliru

#include <boost/variant.hpp>
#include <complex>
#include <string>
#include <vector>
#include <boost/unordered_map.hpp>

using boost::unordered_map;

struct Variant : boost::variant<
                            boost::blank,
                            std::string,
                            std::vector< std::string >,
                            std::vector< int32_t >,
                            std::vector< int64_t >,
                            std::vector< double >,
                            std::vector< std::complex<double> >,
                            unordered_map< std::string, Variant >
                         > 
{
    using base_type = boost::variant<
            boost::blank,
            std::string,
            std::vector< std::string >,
            std::vector< int32_t >,
            std::vector< int64_t >,
            std::vector< double >,
            std::vector< std::complex<double> >,
            unordered_map< std::string, Variant >
         >;

    using base_type::base_type;
    using base_type::operator=;
};

int main() {
    Variant v = unordered_map<std::string, Variant> { {"hello", Variant{"world"} } };
}

这样做的原因是因为映射是一个基于节点的容器:它已经将映射类型的分配与其物理布局解耦,这是您需要递归类型包装器的主要原因。

另请参阅此处,了解另一种情况,其中对此进行了更详细的解释:Recursive using declaration with boost variant

关于c++ - boost::recursive_variant 接受 map,但拒绝 unordered_map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49297004/

相关文章:

c++ - 让getline检查输入文件的第二行和第三行

c++ - 使用一个动态分配的内存块创建 2d 或 3d 数组

c++ - 如何返回映射到可变参数位置的类型

c++ - 如何使用 C++ 和 Boost 查找纽约本地时间?

c++ - 如何确保成员函数被调用一次

c++ - 是否有用于 OpenNI2 的 CMakeLists?

c++ - 如何检查线段是否与任何线相交?

c++ - libboost 中的 undefined symbol

c++ - 在堆栈上创建一个对象,然后通过引用传递给 C++ 中的另一个方法

c++ - 如何使用 Boost::Geometry _union 与整数