2015-12-30 20 views
5

Các biên dịch sau đây trừ khi B0RKEN được định nghĩa (như với -DB0RKEN trên dòng lệnh):'make_shared' là mơ hồ

#include <functional> 
#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 

using boost::shared_ptr; 
using boost::make_shared; 

using my_fn = std::function<void()>; 

void foo() 
{ 
     my_fn fn = [](){}; 

#ifdef B0RKEN 
     shared_ptr<my_fn> k = make_shared<my_fn>(fn); 
#else 
     shared_ptr<int> k = make_shared<int>(0); 
#endif 
} 

Nó có vẻ như tăng được chơi một số trò chơi vui nhộn, có thể là lý do tại sao đoạn mã này có vấn đề này. Những gì tôi không hiểu là lý do tại sao nó hoạt động với shared_ptr<int> nhưng không phải là shared_ptr<my_fn>.

Tôi không quan tâm đến việc tranh luận liệu tôi có nên sử dụng các con trỏ được chia sẻ hay được chia sẻ hay không.

tôi nhận được lỗi sau từ kêu vang ++:

foo.cpp:15:24: error: call to 'make_shared' is ambiguous 
     shared_ptr<my_fn> k = make_shared<my_fn>(fn); 
           ^~~~~~~~~~~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4670:1: note: candidate function [with _Tp = 
     std::__1::function<void()>, _Args = <std::__1::function<void()> &>] 
make_shared(_Args&& ...__args) 
^ 
/opt/local/include/boost/smart_ptr/make_shared_object.hpp:246:87: note: candidate function [with T = std::__1::function<void()>, Args = 
     <std::__1::function<void()> &>] 
template< class T, class... Args > typename boost::detail::sp_if_not_array<T>::type make_shared(Args && ... args) 
                        ^
1 error generated. 

Và từ g ++:

foo.cpp: In function ‘void foo()’: 
foo.cpp:15:45: error: call of overloaded ‘make_shared(my_fn&)’ is ambiguous 
    shared_ptr<my_fn> k = make_shared<my_fn>(fn); 
              ^
foo.cpp:15:45: note: candidates are: 
In file included from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/make_shared.hpp:15:0, 
       from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/make_shared.hpp:15, 
       from foo.cpp:3: 
PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/make_shared_object.hpp:246:87: note: typename boost::detail::sp_if_not_array<T>::type boost::make_shared(Args&& ...) [with T = std::function<void()>; Args = {std::function<void()>&}; typename boost::detail::sp_if_not_array<T>::type = boost::shared_ptr<std::function<void()> >] 
template< class T, class... Args > typename boost::detail::sp_if_not_array<T>::type make_shared(Args && ... args) 
                        ^
In file included from PATH_TO_TOOLCHAIN/gcc-4.9.3/include/c++/4.9.3/memory:82:0, 
       from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/config/no_tr1/memory.hpp:21, 
       from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/shared_ptr.hpp:23, 
       from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/shared_ptr.hpp:17, 
       from foo.cpp:2: 
PATH_TO_TOOLCHAIN/gcc-4.9.3/include/c++/4.9.3/bits/shared_ptr.h:600:5: note: std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = std::function<void()>; _Args = {std::function<void()>&}] 
    make_shared(_Args&&... __args) 
    ^
+0

Trình biên dịch, thông báo lỗi, phiên bản tăng cường nào? – rhashimoto

+0

Bạn có 'sử dụng không gian tên std' hoặc' sử dụng std :: make_shared'? –

Trả lời

12

Loại my_fnstd::function<void()>;, trú tại namespace std.

Khi bạn cố gắng gọi , bạn sẽ thấy cả phiên bản tăng cường (vì bạn đã viết using boost::make_shared;) và phiên bản tiêu chuẩn theo ADL.

int không thuộc về std không gian tên và phiên bản tiêu chuẩn của make_shared không được xem xét.

Ưu tiên sử dụng tên đủ điều kiện thay vì khi có thể để tránh những vấn đề như vậy.

+0

Cảm ơn. Tôi có một câu hỏi kéo dài. Các tác phẩm sau: "shared_ptr > k = make_shared > (0);". Tôi tự hỏi tại sao ADL không đá ở đây, nhưng nó cho những thứ khác trong std (như std :: string). –

+0

@GaryJackson ADL hoạt động cho các đối số chức năng. Trong ví dụ của bạn, đối số là '0' là' int' và không kích hoạt ADL. –

+2

Thật thú vị, ADL sẽ * chỉ * đá ở đây khi nó tìm thấy một mẫu chức năng với tên đó mà không có ADL, như được giải thích [ở đây] (http://stackoverflow.com/questions/2953684/why-doesnt-adl-find-function -templates). Bạn có thể tự kiểm tra điều này - việc loại bỏ các câu lệnh using cho 'boost :: make_shared' sẽ ngăn cản trình biên dịch phù hợp tìm ra' std :: make_shared'. – jaggedSpire