2014-10-15 16 views
13

Tôi đang cố gắng sử dụng std::make_unique để instanciate một lớp có hàm tạo là nhận std::initializer_list. Dưới đây là một trường hợp tối thiểu:Gọi hàm initializer_list thông qua make_unique/make_shared

#include <string> 
#include <vector> 
#include <initializer_list> 
#include <memory> 

struct Foo { 
    Foo(std::initializer_list<std::string> strings) : strings(strings) {} 

    std::vector<std::string> strings; 
}; 

int main(int, char**) { 

    auto ptr = std::make_unique<Foo>({"Hello", "World"}); 

    return 0; 
} 

Bạn có thể nhìn thấy trên Coliru rằng nó không xây dựng:

main.cpp:14:56: error: no matching function for call to 'make_unique(<brace-enclosed initializer list>)' 
    auto ptr = std::make_unique<Foo>({"Hello", "World"}); 

Vì vậy, là make_unique báo cáo không thể sử dụng initializer_list s? Có lỗi trong GCC 4.9.1 không? Hay tôi đã bỏ qua điều gì đó?

+2

Không thể suy ra danh sách đã lập biểu bằng cách khấu trừ đối số mẫu. Hãy thử 'make_unique (std :: initializer_list ({" Hello "," World "}))'. –

+0

@KerrekSB Vâng, trông giống như một câu trả lời cho tôi :) – Quentin

+0

Hm, nó có hoạt động không, và nó có giúp ích gì không? –

Trả lời

20

std::make_unique là mẫu chức năng loại trừ các loại đối số được chuyển tới hàm tạo đối tượng. Thật không may, các danh sách được sắp xếp không được khấu trừ (với một ngoại lệ cho các khai báo auto), và do đó bạn không thể khởi tạo mẫu chức năng khi thiếu kiểu tham số đó.

Bạn không thể sử dụng std::make_unique, nhưng vui lòng không đi theo tuyến đường đó – bạn nên tránh naked new s nhiều nhất có thể, vì lợi ích của trẻ em. Hoặc bạn có thể làm công việc loại trừ bằng cách xác định các loại:

  • std::make_unique<Foo>(std::initializer_list<std::string>({"Hello", "World"}))

  • std::make_unique<Foo, std::initializer_list<std::string>>({"Hello", "World"})

  • auto il = { "Hello"s, "World"s }; auto ptr = std::make_unique<Foo>(il);

Tùy chọn cuối cùng sử dụng quy tắc đặc biệt cho auto tờ khai , (như tôi đã nói ở trên) làm trong thực tế suy ra một std::initializer_list.

2

Nếu bạn đang chuẩn bị để gõ một vài ký tự phụ, bạn có thể làm điều này:

auto ptr = std::make_unique<Foo>(make_init_list({ "Hello"s , "World"s })); 

nơi init_list được định nghĩa là

template<typename T> 
std:: initializer_list<T> make_init_list (std:: initializer_list<T> && l) { 
    return l; 
} 

Điều này cho phép khấu trừ xảy ra, và thuận tiện nếu có nhiều nơi trong mã bạn phải làm điều này. .

(Hoạt động trên kêu vang 3.9 và 6.2.0 gcc tôi đã nhận nó để làm việc trên g ++ -. 4.8.4 cũng có, ngoại trừ tôi phải chỉnh std::string -literal và thay đổi để make_shared Nhưng trừ T trong make_init_list làm việc tốt.)

Thực ra, đây có phải là tiện ích mở rộng không? Có khấu trừ thành công cho make_init_list theo yêu cầu của tiêu chuẩn hay không?

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