【问题标题】:c++ access elements of the array in a map [duplicate]c ++访问地图中数组的元素[重复]
【发布时间】:2012-11-11 17:30:05
【问题描述】:

可能重复:
Using array as map value: Cant see the error

假设我有以下数据结构:

std::map<size_t, double[2] > trace;

如何使用 operator[] 访问其元素?

基本上我想做这样的事情:

trace[0][0] = 10.0;
trace[0][1] = 11.0;

在编译这些代码行时,我收到以下错误:

/usr/include/c++/4.6/bits/stl_map.h:453:11: error: conversion from ‘int’ to non-scalar type ‘std::map<long unsigned int, double [2]>::mapped_type {aka double [2]}’ requested

cmets?

【问题讨论】:

  • std::map&lt;size_t, double[2] &gt; 合法吗?我不认为你可以像那样在 STL 中使用数组。
  • 这篇文章可能对你有所帮助stackoverflow.com/questions/2582529/…
  • 考虑改用std::map&lt;int, std::array&lt;double, 2&gt;&gt;(如果你有这种可能性,否则std::map&lt;int, boost::array&lt;double, 2&gt; &gt;
  • 这是不合法的。 c 样式数组不可复制构造,因此不能用作映射值。你用的是什么编译器? gcc 对 ISO C++ forbids casting to an array type double[2] 大喊大叫
  • @ybungalobill:但我认为它们是默认可构造的,这就是它们所需要的。如果你想使用insert,它们只需要复制或移动构造即可。

标签: c++ arrays map


【解决方案1】:

地图的值类型必须是默认可构造的,使用表达式value_type(),以便通过[] 访问它们。由于某种神秘的原因,数组类型不是 C++11 5.3.2/2 中指定的(我强调):

表达式 T(),其中 T 是 非数组 完整对象类型的简单类型说明符或类型名称说明符...创建指定类型的纯右值,即值初始化

编译器在尝试对数组进行值初始化时给出了奇怪的错误;以下给出了相同的错误:

typedef double array[2];
array();

我建议使用类类型而不是 double[2]std::array&lt;double,2&gt;std::pair&lt;double,double&gt; 或包含两个双精度的 struct。此类类型是可复制的,不会立即衰减为指针(丢失大小的编译时知识),并且通常比内置数组类型更容易处理。

如果您对不提供std::array 的旧库感到困扰,那么您可以使用非常相似的Boost.Array,或者编写自己的简单类模板来包装数组。

【讨论】:

    【解决方案2】:

    你可以包装一个数组:

    template<typename T, unsigned int n>
    struct ArrayWrapper
    {
        T v[n];
        T& operator[](unsigned int i) { return v[i]; } // You can also check for out-of-bounds errors
        const T& operator[](unsigned int i) const { return v[i]; } // You can also check for out-of-bounds errors
    };
    #include <map>
    #include <iostream>
    int main()
    {
        typedef std::map<size_t, ArrayWrapper<double,2> > Map;
        Map trace;
        trace[1][0] = 42;
        for(Map::const_iterator it = trace.begin(); it != trace.end(); ++it)
            std::cout << "( " << (*it).first
                << ", " << (*it).second[0]
                << ", " << (*it).second[1]
                << ")\n";
    }
    

    Live example。否则,如果你有 C++11,你应该使用std::array;如果没有,并且你有 Boost,你可以使用 Boost.Array。

    【讨论】:

      【解决方案3】:

      你的代码编译到:

      std::map<size_t, double[2]> trace;
      

      因为double[2] 是有效类型。您可以声明具有任何有效类型的模板类对象。例如:

      template<typename T>
      struct X {
        // T t; // this will complain for sure
        void foo () { T t; } // this won't complain unless invoked !!
      };
      X<void> x;
      

      将编译没有任何问题。
      如果你调用x.foo(),编译器会报错。

      std::map 也会发生同样的事情。当您调用 map::insert()map::operator [] 之类的函数时,实际上将使用值类型 double[2],编译器将开始抱怨 double[2] 不可复制(异常:我见过旧的 g++3.x 版本,其中数组是可分配和可复制的)。

      您可以将数组封装到一个结构中。

      struct D { double d[2]; };
      

      如果您想避免使用原始数组,那么 std::array 是 cmets 和其他答案中提到的不错选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        • 2019-07-02
        • 2020-02-28
        相关资源
        最近更新 更多