Opened 7 years ago

Last modified 7 years ago

#12019 new Bugs

Conversion from unique_ptr to shared_ptr is too broad

Reported by: Tavian Barnes <tavianator@…> Owned by: Peter Dimov
Milestone: To Be Determined Component: smart_ptr
Version: Boost 1.60.0 Severity: Problem
Keywords: Cc:

Description

The following program doesn't compile because the foo overload is ambiguous. This applies if boost::movelib::unique_ptr is used as well. It works if std::shared_ptr is used instead of boost::shared_ptr.

$ cat foo.cpp #include <boost/shared_ptr.hpp> #include <memory>

using boost::shared_ptr; using std::unique_ptr; using std::make_unique;

template <typename T> class Provider { };

template <typename T> void foo(shared_ptr<T> ptr) { }

template <typename T> void foo(unique_ptr<Provider<T>> ptr) { }

class IntProvider : public Provider<int> { };

void bar() {

foo<int>(make_unique<IntProvider>());

} $ g++ -std=c++14 -c foo.cpp foo.cpp: In function ‘void bar()’: foo.cpp:24:38: error: call of overloaded ‘foo(std::_MakeUniq<IntProvider>::single_object)’ is ambiguous

foo<int>(make_unique<IntProvider>());

foo.cpp:13:6: note: candidate: void foo(boost::shared_ptr<X>) [with T = int]

void foo(shared_ptr<T> ptr)

foo.cpp:17:6: note: candidate: void foo(std::unique_ptr<Provider<T> >) [with T = int]

void foo(unique_ptr<Provider<T>> ptr)

The boost::shared_ptr<T> taking unique_ptr<Y, D> should be SFINAE'd away when unique_ptr<Y, D>::pointer isn't convertible to T*.

The std::shared_ptr DR is #2399: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2399

Change History (1)

comment:1 by Tavian Barnes <tavianator@…>, 7 years ago

Argh, messed up the formatting. Should read like this:

---

The following program doesn't compile because the foo overload is ambiguous. This applies if boost::movelib::unique_ptr is used as well. It works if std::shared_ptr is used instead of boost::shared_ptr.

$ cat foo.cpp
#include <boost/shared_ptr.hpp>
#include <memory>

using boost::shared_ptr;
using std::unique_ptr;
using std::make_unique;

template <typename T>
class Provider
{ };

template <typename T>
void foo(shared_ptr<T> ptr)
{ }

template <typename T>
void foo(unique_ptr<Provider<T>> ptr)
{ }

class IntProvider : public Provider<int>
{ };

void bar() {
  foo<int>(make_unique<IntProvider>());
}
$ g++ -std=c++14 -c foo.cpp
foo.cpp: In function ‘void bar()’:
foo.cpp:24:38: error: call of overloaded ‘foo(std::_MakeUniq<IntProvider>::__single_object)’ is ambiguous
   foo<int>(make_unique<IntProvider>());
                                      ^
foo.cpp:13:6: note: candidate: void foo(boost::shared_ptr<X>) [with T = int]
 void foo(shared_ptr<T> ptr)
      ^
foo.cpp:17:6: note: candidate: void foo(std::unique_ptr<Provider<T> >) [with T = int]
 void foo(unique_ptr<Provider<T>> ptr)
      ^

The boost::shared_ptr<T> constructor taking unique_ptr<Y, D> should be SFINAE'd away when unique_ptr<Y, D>::pointer isn't convertible to T*.

The std::shared_ptr DR is #2399: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2399

Note: See TracTickets for help on using tickets.