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 は非配列完全オブジェクト型の単純型指定子または型名指定子です ... 指定された型の prvalue を作成し、値が初期化されます

配列を値で初期化しようとすると、コンパイラはその奇妙なエラーを出します。以下は同じエラーを返します:

typedef double array[2];
array();

double[2]: std::array<double,2>std::pair<double,double>、またはstruct2 つの double を含むaではなく、クラス型を使用することをお勧めします。このような型はコピー可能であり、すぐにポインターに分解されず (サイズに関するコンパイル時の知識が失われます)、一般的に組み込みの配列型よりも扱いが簡単です。

を提供しない古いライブラリに行き詰まっている場合はstd::array、非常によく似たBoost.Arrayを使用するか、独自の単純なクラス テンプレートを記述して配列をラップすることができます。

于 2012-11-23T11:18:11.147 に答える
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ます。value-typeが実際map::insert()に使用される のような関数を呼び出すと、コンパイラはコピーできないと文句を言い始めます(例外: 配列が代入可能でコピー可能な古い g++3.x バージョンを見てきました)。map::operator []double[2]double[2]

配列を構造体にカプセル化できます。

struct D { double d[2]; };

生の配列の使用を避けたい場合std::arrayは、コメントやその他の回答に記載されているように、適切なオプションです。

于 2012-11-23T11:25:07.103 に答える
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 に答える