【问题标题】:initialize submaps in std::map<..., boost::any>在 std::map<..., boost::any> 中初始化子图
【发布时间】:2015-11-10 16:53:57
【问题描述】:

在初始化std::map&lt;std::string, boost::any&gt; 时,boost::any 的值确实可以采用任何类型的值,包括std::maps。但是,它们需要首先明确定义,例如,

#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>’

怎么了?有没有办法将初始化放入一个语句中?

【问题讨论】:

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


    【解决方案1】:

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

    给他一些帮助:

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

    问题解决了。

    【讨论】:

    • 好答案。关于“不知道什么类型”——一个例子是{{"y", 2}}——单独考虑——同样可以是boost::anyvectorlist。将其与其他语言进行对比很有趣,在这些语言中,动态创建关联容器有不同的表示法(例如,Ruby 中的{ "y" =&gt; 2 },python 中的{ "y": 2 }),但这使得替换另一个关联容器变得困难——也许性能更好或特定用途的内存利用率 - 无需更改所有客户端代码。
    【解决方案2】:

    一般来说,你像这样大括号初始化std::map&lt;K, V&gt;

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

    其中k1k2etc.用于初始化key,v1v2etc.用于初始化映射的值。

    现在我们可以看到,为了做你想做的事情,必须可以从你在v2的位置上初始化映射类型boost::any,即{{"y", 2}}

    而这是无法做到的。你做不到

    boost::any a = {{"y", 2}};
    

    因此,您尝试初始化地图的方式也行不通。

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

    braced-init-list 只能用于初始化。它用于确定使用哪个构造函数进行初始化,然后将其内容传递给所选的构造函数。尝试像这样从 braced-init-list 初始化 boost::any 是行不通的,因为编译器无法推断出您想先将 {{"y", 2}} 转换为映射然后包装boost::any里面的那张地图。

    解决方案是显式执行此转换。

    std::map<std::string, boost::any> any = {
      {"hh", 4},
      {"g", std::map<std::string, boost::any>{{"y", 2}} }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      相关资源
      最近更新 更多