8

可能重复:
使用数组作为映射值:看不到错误

假设我有以下数据结构:

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

评论?

4

3 回答 3

5

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

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

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

typedef double array[2];
array();

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

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

于 2012-11-23T11:18:11.147 回答
1

您可以包装一个数组:

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";
}

活生生的例子。否则,如果你有 C++11,你应该使用std::array; 如果没有,并且您有 Boost,则可以使用 Boost.Array。

于 2012-11-23T11:20:55.520 回答
1

您的代码编译到:

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()时,编译器将开始抱怨不可复制(例外:我见过一个旧的 g++3.x 版本,其中数组是可分配和可复制的)。map::operator []double[2]double[2]

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

struct D { double d[2]; };

如果您想避免使用原始数组,那么std::array如评论和其他答案中所述,这是一个不错的选择。

于 2012-11-23T11:25:07.103 回答