在std :: map< ...,boost :: any>中初始化子图

时间:2015-08-17 22:34:41

标签: c++ c++11 dictionary boost

初始化std::map<std::string, boost::any>时,值boost::any确实可以包含任何类型的值,包括std::map s。但是,它们需要首先明确定义,例如,

#include <map>
#include <boost/any.hpp>
int main() {
  std::map<std::string, boost::any> a = {{"y", 2}};

  std::map<std::string, boost::any> any = {
    {"hh", 4},
    {"g", a}  // alright
  };
}

隐含地尝试同样的事情,例如,

#include <map>
#include <boost/any.hpp>
int main() {
  std::map<std::string, boost::any> any = {
    {"hh", 4},
    {"g", {{"y", 2}}}  // mööp
  };
}

导致编译错误

error: could not convert ‘{{"hh", 4}, {"g", {{"y", 2}}}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<std::__cxx11::basic_string<char>, boost::any>’

出了什么问题?有没有办法让初始化适合一个语句?

2 个答案:

答案 0 :(得分:9)

好吧,编译器无法知道你的初始化列表最终应该成为什么类型。

给他一些帮助:

#include <map>
#include <boost/any.hpp>

using namespace std;

int main() {
  using StringToAny = std::map<std::string, boost::any>;
  StringToAny any = {
    {"hh", 4},
    {"g", StringToAny{{"y", 2}}}  // jippie!
  };
}

问题解决了。

答案 1 :(得分:6)

一般来说,像这样大括号std::map<K, V>

std::map<K, V> m = {{k1, v1}, {k2, v2}, ...};

其中k1k2等。用于初始化密钥,v1v2等。 用于初始化映射值。

现在我们可以看到,为了完成您要执行的操作,必须可以从boost::any的位置初始化映射类型v2,即{ {1}}。

这是不可能做到的。你做不到

{{"y", 2}}

因此,您尝试初始化地图的方式也无法正常工作。

我看到这个问题是你今天早些时候发布的另一个问题的后续问题,而且你是来自Python背景。您的背景可能会让您相信boost::any a = {{"y", 2}}; 本身代表一个地图,{{"y", 2}}是Python中字典文字的方式。但是,在C ++中并非如此;相反,{'y': 2}没有类型,甚至根本不是表达式;它是一个特殊的语法类别,名为 braced-init-list

braced-init-list 只能用于初始化。它用于确定用于初始化的构造函数,然后将其内容传递给所选的构造函数。尝试从这样的 braced-init-list 初始化{{"y", 2}}不起作用,因为编译器无法推断出您希望首先将boost::any转换为映射然后将该映射包装在{{"y", 2}}

解决方案是明确执行此转换。

boost::any