2012-11-23 12 views
8

Possible Duplicate:
Using array as map value: Cant see the errorC++ Zugriffselemente des Arrays in einer Karte

nehme ich die folgende Datenstruktur:

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

wie kann ich seine Elemente mit dem Operator Zugriff []?

Grunde möchte ich etwas tun:

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

In diesen Zeilen Code kompilieren ich die folgende Fehlermeldung erhalten:

/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 

Kommentare?

+0

Sie haben eine Reihe von Doppel in der Karte. Die Karte benötigt einen Schlüssel zum Speichern/Binden eines Werts an. Wie haben Sie der Karte Werte zugewiesen? –

+1

'std :: map ' ist das legal? Ich dachte nicht, dass Sie Arrays in der STL so verwenden könnten. – john

+2

dieser Beitrag könnte Ihnen helfen, http://stackoverflow.com/questions/2582529/using-array-as-map-value-cant-see-the-error – denizeren

Antwort

5

Werttypen für Maps müssen standardmäßig dekomponierbar sein, indem ein Ausdruck value_type() verwendet wird, um über [] darauf zugreifen zu können. Aus unerfindlichen Gründen, Array-Typen sind nicht, wie ++ 11 5.3.2/2 in C angegeben (mit Hervorhebung von mir):

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type ... creates a prvalue of the specified type,which is value-initialized

Der Compiler gibt diese seltsame Fehler, wenn sie versuchen, ein Array-Wert initialisieren; Im Folgenden werden die gleichen Fehler:

typedef double array[2]; 
array(); 

ich einen Klassentyp empfehlen die Verwendung anstatt double[2]: std::array<double,2>, std::pair<double,double> oder ein struct mit zwei Doppelzimmer. Solche Typen sind kopierbar, zerfallen nicht in einen Zeiger (verlieren das Wissen über die Größe der Kompilierung) und sind im Allgemeinen einfacher zu handhaben als ein eingebauter Array-Typ.

Wenn Sie mit einer alten Bibliothek stecken, die nicht bietet, dann könnten Sie die sehr ähnliche Boost.Array verwenden, oder schreiben Sie Ihre eigene einfache Klassenvorlage, um ein Array zu umhüllen.

1

Sie können ein Array wickeln:

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. Sonst, wenn Sie C++ 11 haben, sollten Sie verwenden; Wenn nicht, und Sie Boost haben, können Sie Boost.Array verwenden.

1

Ihr Code kompiliert werden bis:

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

weil double[2] gültiger Typ ist. Sie können ein Vorlagenklassenobjekt mit einem beliebigen gültigen Typ deklarieren. Zum Beispiel:

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; 

kompiliert wird ohne jedes Problem.
Wenn Sie x.foo() aufrufen, wird der Compiler darüber beschweren.

Dasselbe geschieht im Fall von std::map. Wenn Sie Funktionen aufrufen, wie map::insert(), map::operator [], wo der Wert-Typ double[2] tatsächlich verwendet werden soll, wird der Compiler beschweren starten als double[2] nicht kopierbar ist (Ausnahme: Ich habe einen alten g ++ 3.x-Version, wo Arrays gesehen waren zuweisbar und kopierbar).

Sie können Ihr Array in eine Struktur einzukapseln.

struct D { double d[2]; }; 

Wenn Sie möchten, mit rohen Array vermeiden, dann ist std::array gute Option, da in den Kommentaren und anderen Antwort erwähnt.