boost :: recursive_variant接受map,但拒绝unordered_map

时间:2018-03-15 10:26:13

标签: 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,提升1.58。

2 个答案:

答案 0 :(得分:2)

问题似乎与您的特定设置有关。我无法使用以下所有配置重现它。

此外,全面抽样测试包括

Variant v = std::unordered_map<std::string, Variant> { {"hello", Variant{"world"} } };
在主要内部所有人也编译顺利。

使用libstdc ++的GCC

使用libc ++

答案 1 :(得分:2)

哈。你的评论随便提到SWIG让我的脑袋里出现了一个灯泡。

我不会在涉及boost::[make_recursive_]variant的任何事情上信任SWIG。现在您提到了这一点,我很清楚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"} } };
}

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

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