2015-09-18 12 views
6

Tôi muốn triển khai bản đồ, ánh xạ một chuỗi thành một vectơ chung.Bản đồ STL tới vector chung C++

Tôi muốn làm điều này:

std::map<std::string, std::vector<class T> > myMap; 

Giả sử myMap đề xuất đã sau đây nhét vào đó, nó có thể được sử dụng như ví dụ:

vector<int> intVec = myMap["ListOfInts"]; // Works because "ListOfInts" maps to a vector<int> 
vector<string> stringVec = myMap["ListOfStrings"]; // Works because "ListOfInts" maps to a vector<string> 

Khi tôi tuyên bố bản đồ với ở trên cú pháp trình biên dịch có một cơn đau tim.

Có ai có thể đưa ra bất kỳ đề xuất nào không? Hoặc một tùy chọn mảng liên kết tốt hơn trong C++ (đề xuất không tăng trước khi tăng).

+4

Bạn sẽ cần giá trị bản đồ của bạn trở thành một loại biến thể, không có loại biến thể tiêu chuẩn do đó bạn sẽ phải thực hiện của riêng bạn hoặc sử dụng một cái gì đó như ['boost :: variant'] (http://www.boost.org/doc/libs/1_59_0/doc/html/variant.html). – mattnewport

+0

Có bao nhiêu 'T' khác nhau bạn cần cho std :: vector ? Bạn có thể lấy ra với một container đa hình nếu bạn có thể tìm ra những gì để đúc thông qua RTTI hoặc thông qua một số loại ID bạn thực hiện chính mình. – VoidStar

+1

C++ được nhập tĩnh và các loại giá trị bản đồ phải giống nhau trong một bản đồ. Nếu bạn nói với chúng tôi vấn đề thực sự bạn đang cố gắng giải quyết, chúng tôi có thể chỉ ra một cách C++ - thành ngữ, hoặc nhìn vào 'boost :: variant'. –

Trả lời

2

Vì bạn biết loại bạn muốn khi bạn đang viết mã của bạn, tôi đề xuất phương pháp này (chưa được kiểm tra):

// base class for any kind of map 
class BaseMap { 
public: 
    virtual ~BaseMap() {} 
}; 

// actual map of vector<T> 
template<typename T> 
class MapT : public BaseMap, public std::map<std::string, std::vector<T>> {}; 

class MultiMap { 
public: 
    template<typename T> 
    std::vector<T>& get(const std::string& key) { 
    std::unique_ptr<BaseMap>& ptr = maps_[std::type_index(typeid(T))]; 
    if (!ptr) ptr.reset(new MapT<T>()); 
    return ptr->second[key]; 
    } 
private: 
    std::map<std::type_index, std::unique_ptr<BaseMap>> maps_; 
} 

int main() { 
    MultiMap map; 
    std::vector<int>& intVec = map.get<int>("ListOfInts"); 
    std::vector<std::string>& stringVec = map.get<std::string>("ListOfStrings"); 
} 
-2

Đối số mẫu phải được quyết định thời gian biên dịch. Nếu bạn muốn mỗi khóa của bản đồ tương ứng với một vectơ thuộc một loại khác, nó sẽ không thực sự hoạt động. Bạn có thể thu thập nó với một container đa hình trả về một khoảng trống * mà bạn đưa vào đúng loại, nhưng tôi khuyên bạn nên tìm cách khác để làm bất cứ điều gì bạn muốn làm với bản đồ của bạn trước.

+0

Vùng chứa đa hình có lẽ không nên chứa trả về 'void *', vì nó không cung cấp một cách để tìm ra loại đó là gì. Tốt hơn sẽ được yêu cầu rằng các container chính nó là upcast (thông qua một chuyển đổi trên typeid hoặc một id tùy chỉnh) để các lớp con thích hợp và sau đó loại thực được trả lại. – VoidStar

+0

Nếu nó trả về một khoảng trống *, nó giả định rằng người gọi biết loại nó trả về. Rất không an toàn. Tôi cho rằng upcasting có thể an toàn hơn rất nhiều. – fuzzything44

+0

là "ListOfInts" chỉ đề cập đến vector ? – ggrr

0

Có lẽ điều này có thể làm việc cho bạn:

template <typename T> 
class MyMap { 
    std::map<std::string, std::vector<typename T> > map; 
public: 
    /*...*/ 
}; 
0

Với C++ 11, bạn có thể sử dụng using, nó thực hiện chính xác những gì bạn muốn:

#include <vector> 
#include <map> 
#include <string> 

template<typename T> using mymap = std::map<std::string, std::vector<T>>; 

int main() 
{ 
    mymap<int> intmap; 
    mymap<std::string> stringmap; 

    std::vector<int> intvec = intmap["test"]; 
    std::vector<std::string> stringvec = stringmap["test"]; 

    return 0; 
} 

Live Demo

+0

Cảm ơn bạn đã gợi ý, nhưng đây không phải là những gì tôi muốn làm. Tôi không muốn tạo nhiều hơn một bản đồ, nhưng bên trong nó lưu trữ nhiều vectơ bất kỳ loại nào. –

+0

Không có vấn đề ;-) Sau khi đọc câu hỏi của bạn một lần nữa, tôi nghĩ rằng tôi nên đã tìm thấy rằng ra bản thân mình. Tôi đoán tôi đã nhầm lẫn vì nó không phải là một cách điển hình C++ để làm điều đó. – alain

0

Như mattnewport cho biết boost::variant là một tùy chọn.

Hoặc để hỗ trợ bất kỳ loại nào, hãy sử dụng boost::any bằng cách sử dụng rõ ràng any_cast.

Xem xét tăng có thể là trọng lượng nặng, có thể bạn có thể tái tạo lại bánh xe và đơn giản hóa nó, để không tăng thêm nữa? lol

Các vấn đề liên quan