2016-04-06 28 views
8

Tôi đã sau shared_ptr đến một map:Initialising std :: shared_ptr <std::map<>> sử dụng chuẩn bị tinh thần-init

std::shared_ptr<std::map<double, std::string>> 

và tôi muốn khởi nó sử dụng chuẩn bị tinh thần-init. Có thể không?

Tôi đã thử:

std::string s1("temp"); 
std::shared_ptr<std::map<double, std::string>> foo = std::make_shared<std::map<double, std::string>>(1000.0, s1); 

nhưng điều đó mang lại cho các lỗi sau khi biên soạn sử dụng Xcode 6.3:

/usr/include/c++/v1/map:853:14: Candidate constructor not viable: no known conversion from 'double' to 'const key_compare' (aka 'const std::__1::less<double>') for 1st argument 

Tôi đã thử các biến thể khác của tham số đầu tiên (1000.0) nhưng không thành công .

Có ai giúp được không?

+0

có thể, nhưng không đẹp, 'std :: shared_ptr > foo = std :: mak e_shared > (std :: initializer_list :: value_type> {{1000.0, s1}}); ' –

+0

hoặc chỉ 'std :: shared_ptr > foo = std :: make_shared > (std :: map {{1000.0, s1}}); 'nhưng vẫn không đẹp –

+0

Điều đó có hiệu quả. Tôi lưu ý việc sử dụng 'value_type'. Tôi chỉ thấy cặp 'typedef 'của nó '. Tại sao tôi cần điều đó? – ksl

Trả lời

8

std::map có một constructor khởi tạo danh sách:

map (initializer_list<value_type> il, 
    const key_compare& comp = key_compare(), 
    const allocator_type& alloc = allocator_type()); 

Chúng ta có thể tạo ra một bản đồ sử dụng constructor này khá dễ dàng:

std::map<double,std::string> m1{{1000.0, s1}}; 

Để sử dụng nó trong make_shared, chúng ta cần phải xác định những instantiation của initializer_list chúng tôi đang cung cấp:

auto foo = std::make_shared<std::map<double,std::string>> 
      (std::initializer_list<std::map<double,std::string>::value_type>{{1000.0, s1}}); 

Điều đó có vẻ thực sự vụng về; nhưng nếu bạn cần điều này thường xuyên, bạn có thể dọn dẹp nó lên với bí danh:

#include <string> 
#include <map> 
#include <memory> 

std::string s1{"temp"}; 

using map_ds = std::map<double,std::string>; 
using il_ds = std::initializer_list<map_ds::value_type>; 

auto foo = std::make_shared<map_ds>(il_ds{{1000.0, s1}}); 

Bạn thay vì có thể thích để định nghĩa một hàm template để bọc các cuộc gọi:

#include <string> 
#include <map> 
#include <memory> 

template<class Key, class T> 
std::shared_ptr<std::map<Key,T>> 
make_shared_map(std::initializer_list<typename std::map<Key,T>::value_type> il) 
{ 
    return std::make_shared<std::map<Key,T>>(il); 
} 

std::string s1{"temp"}; 
auto foo = make_shared_map<double,std::string>({{1000, s1}}); 
+2

Bạn có thể tạo 'il_double_to_string' một mẫu bí danh để nó có thể hoạt động với bất kỳ loại bản đồ nào. Một cái gì đó như [this] (http://coliru.stacked-crooked.com/a/2e73df08f6d1070a). – TartanLlama

+0

Trong trường hợp quan trọng, tôi đã sử dụng GCC 4.8.2 để kiểm tra ở trên. –

-2

someting tương tự như sau nên làm điều đó ...

std::string s1("temp"); 

std::map<double, std::string> *m = new std::map<double, std::string>{{100., s1}}; 

auto foo = std::shared_ptr<std::map<double, std::string>>(m); 

hoặc như một oneliner

auto foo2 = std::shared_ptr<std::map<double, std::string>>(new std::map<double, std::string>{{100., s1}}); 

(Xin lỗi, đầu tiên bỏ lỡ các yêu cầu về danh sách initializer)

-4

Thay đổi phím của kiểu.

double là loại không hợp lệ cho khóa vì không có operator== cho nó và chuỗi byte khác nhau có thể đại diện cho cùng một giá trị dấu phẩy động.

+0

Điều này không trả lời được câu hỏi. – dreamlax

+0

Có một toán tử == cho đôi - nhưng bạn cần phải sử dụng nó cẩn thận. –

+1

'std :: map' không quan tâm đến' operator == 'mặc dù, nó không sử dụng nó. –

1

Vấn đề của bạn là bạn không thực sự đặt bất kỳ dấu ngoặc nhọn nào trong trình khởi tạo của mình. Tôi cần những điều sau đây để hoạt động:

auto foo = std::make_shared<std::map<double, std::string> >(
         std::map<double, std::string>({{1000.0, s1}}) 
      ); 

Hai lần std::map<double, std::string> lỗi tôi. Nó thực sự nên có thể làm việc ra một trong số họ cho người khác ... nhưng gcc 5.3.0 sẽ không chơi bóng.

Bạn chắc chắn sẽ cần đôi niềng răng. (Một lần để nói rằng bạn đang khởi tạo một bản đồ, một lần để phân định từng mục nhập.)

+0

Điều đó tạo ra một 'initializer_list', xây dựng một' bản đồ' từ nó, sau đó sao chép bản đồ '. Sẽ tốt hơn nếu chỉ chuyển trực tiếp 'initializer_list' sang' make_shared' và tránh bản sao 'map'. –

+0

Đồng ý hoàn toàn. (Mặc dù có một cơ hội chiến đấu bản đồ sẽ là một động thái, vì vậy nó không * khủng khiếp * đắt tiền.) Tôi không thể làm cho nó hoạt động được. –

+0

... và Toby Speight đã đưa ra câu trả lời đúng. –

0

bạn có thể làm điều đó không có std::make_shared:

std::shared_ptr<std::map<double,std::string>> ptr(new std::map<double,std::string>({{1000.0, "string"}})); 
Các vấn đề liên quan