【问题标题】:Initialising std::shared_ptr<std::map<>> using braced-init使用花括号初始化初始化 std::shared_ptr<std::map<>>
【发布时间】:2016-04-06 08:32:35
【问题描述】:

我有以下shared_ptr 到map:

std::shared_ptr<std::map<double, std::string>>

我想使用braced-init对其进行初始化。有可能吗?

我试过了:

std::string s1("temp");
std::shared_ptr<std::map<double, std::string>> foo = std::make_shared<std::map<double, std::string>>(1000.0, s1);

但是使用 Xcode 6.3 编译时会出现以下错误:

/usr/include/c++/v1/map:853:14: Candidate constructor not viable: no known conversion from 'double' to 'const key_compare' (aka 'const std::__1::less<double>') for 1st argument

我尝试了第一个参数 (1000.0) 的其他变体,但均未成功。

谁能帮忙?

【问题讨论】:

  • 可能,但不漂亮,std::shared_ptr&lt;std::map&lt;double, std::string&gt;&gt; foo = std::make_shared&lt;std::map&lt;double, std::string&gt;&gt;(std::initializer_list&lt;std::map&lt;double, std::string&gt;::value_type&gt;{{1000.0, s1}});
  • 或者只是std::shared_ptr&lt;std::map&lt;double, std::string&gt;&gt; foo = std::make_shared&lt;std::map&lt;double, std::string&gt;&gt;(std::map&lt;double, std::string&gt;{{1000.0, s1}});,但还是不太好
  • 那行得通。我注意到value_type 的使用。我看到它只是typedef pair&lt;const Key, Type&gt;。为什么我需要那个?
  • 问题是您添加的一个对象是 std::pair,因此您需要将 std::pair 放入花括号初始化列表中。编辑:当然是地图。

标签: c++ c++11 shared-ptr stdmap list-initialization


【解决方案1】:

std::map 有一个初始化列表构造函数:

map (initializer_list<value_type> il,
     const key_compare& comp = key_compare(),
     const allocator_type& alloc = allocator_type());

我们可以很容易地使用这个构造函数来创建地图:

std::map<double,std::string> m1{{1000.0, s1}};

要在make_shared 中使用它,我们需要指定我们提供的initializer_list 的实例化:

auto foo = std::make_shared<std::map<double,std::string>>
           (std::initializer_list<std::map<double,std::string>::value_type>{{1000.0, s1}});

这看起来很笨拙;但是如果你经常需要这个,你可以用别名来整理它:

#include <string>
#include <map>
#include <memory>

std::string s1{"temp"};

using map_ds = std::map<double,std::string>;
using il_ds = std::initializer_list<map_ds::value_type>;

auto foo = std::make_shared<map_ds>(il_ds{{1000.0, s1}});

您可能更喜欢定义一个模板函数来包装调用:

#include <string>
#include <map>
#include <memory>

template<class Key, class T>
std::shared_ptr<std::map<Key,T>>
make_shared_map(std::initializer_list<typename std::map<Key,T>::value_type> il)
{
    return std::make_shared<std::map<Key,T>>(il);
}

std::string s1{"temp"};
auto foo = make_shared_map<double,std::string>({{1000, s1}});

【讨论】:

  • 您可以将il_double_to_string 设为别名模板,以便它适用于任何地图类型。类似this.
  • 以防万一,我使用 GCC 4.8.2 来测试上述内容。
【解决方案2】:

您的问题是您实际上并没有在初始化程序中放置任何大括号。我需要以下内容才能让它工作:

auto foo = std::make_shared<std::map<double, std::string> >(
                         std::map<double, std::string>({{1000.0, s1}})
           );

双重std::map&lt;double, std::string&gt; 让我很烦。考虑到另一个,它确实应该能够解决其中一个......但是 gcc 5.3.0 不会打球。

你肯定需要双括号。 (一次是说你正在初始化一个地图,一次是为了分隔每个条目。)

【讨论】:

  • 创建一个initializer_list,从中构造一个map,然后复制map。最好将initializer_list 直接传递给make_shared 并避免map 复制。
  • 绝对同意。 (虽然地图副本很有可能会成为一个移动,所以它并不可怕昂贵。)我无法让它工作。
  • ...Toby Speight 给出了正确的答案。
【解决方案3】:

你可以不用std::make_shared:

std::shared_ptr<std::map<double,std::string>> ptr(new std::map<double,std::string>({{1000.0, "string"}}));

【讨论】:

    【解决方案4】:

    类似的东西应该可以做到...

     std::string s1("temp");  
    
     std::map<double, std::string> *m = new std::map<double, std::string>{{100., s1}};
    
     auto foo = std::shared_ptr<std::map<double, std::string>>(m);
    

    或作为单行者

    auto foo2 = std::shared_ptr<std::map<double, std::string>>(new std::map<double, std::string>{{100., s1}});
    

    (对不起,第一次错过了初始化列表的要求)

    【讨论】:

      【解决方案5】:

      更改密钥的类型。

      double 是一种不好的键类型,因为它没有operator==,而且不同的字节序列可以表示相同的浮点值。

      【讨论】:

      • std::map 不关心operator==,但它不使用它。
      • 不,并非总是如此。如果您将已知值插入到地图中,那么键将恰好具有这些值。浮点数不是不确定的,并且会受到量子涨落的影响。浮点数作为映射键的问题是 NaN 没有按其他值排序。
      • @JonathanWakely: "正是那些值" - 以 0.1 可能不等于 1./10. 的问题为模,特别是如果第一个是文字,而第二个是包含两个变量的表达式价值观。但是,是的,可以小心地完成。
      • @jonezq,不,它确实不取决于实现。 std::map 不允许使用operator==。
      • @jonezq:他不是这么说的。如果您创建一个键为 0.0 的地图,那么您可以搜索负零并找到 0.0 元素。如果您搜索 NaN 元素(相对于其他值没有排序),将会发生不好的事情。如果您使用键 0.1(文字)创建一个元素,然后搜索文字 0.1,您会找到它。如果您搜索 (1.0/10.0),您很可能不会。如果您确实找到了一个元素,那么您搜索的值将与键进行比较。
      猜你喜欢
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多