C++0x Error: overloading a function with std::shared_ptr to const argument is ambiguous

后端 未结 4 558
醉梦人生
醉梦人生 2021-01-18 09:04

Suppose I have two unrelated classes A and B. I also have a class Bla that uses boost::shared_ptr like t

相关标签:
4条回答
  • 2021-01-18 09:26

    The following compiles fine with GCC 4.5 and Visual Studio 10. If you say it doesn't compile in GCC 4.5.2 then it sounds like a compiler bug which you should report (but make sure that it really happens it's more likely that you made some sort of typo).

    #include <memory>
    class A{};
    class B{};
    class Bla {
    public:
        void foo(std::shared_ptr<A>) {}
        void foo(std::shared_ptr<B>) {}
    };
    
    int main()
    {
        Bla bla;
        std::shared_ptr<A> a;
        bla.foo(a);
    }
    
    0 讨论(0)
  • 2021-01-18 09:28

    You can use std::static_pointer_cast to add the const qualification:

    bla.foo(std::static_pointer_cast<const A>(a));
    
    0 讨论(0)
  • 2021-01-18 09:50

    http://bytes.com/topic/c/answers/832994-shared_ptr-derived-classes-ambiguitity-overloaded-functions

    struct yes_type { char dummy; };
    struct no_type { yes_type a; yes_type b; };
    
    template < typename From, typename To >
    class is_convertible
    {
        private:
            static From* dummy ( void );
    
            static yes_type check ( To );
    
            static no_type check ( ... );
    
        public:
    
            static bool const value = sizeof( check( *dummy() ) ) == sizeof( yes_type );
    
    }; // is_convertible
    

    An in boost's shared_ptr.h, change the constructor signature to:

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r,
        typename enable_if<is_convertible<Y*, T*>::value, void*>::type = 0
        ): px(r.px), pn(r.pn) // never throws
    {
    }
    
    0 讨论(0)
  • 2021-01-18 09:51

    shared_ptr has a template single-argument constructor, which is considered for the conversion here. That's what allows an actual parameter shared_ptr<Derived> to be supplied where a shared_ptr<Base> is needed.

    Since both shared_ptr<const A> and shared_ptr<const B> have this implicit conversion, it's ambiguous.

    At least in C++0x, the standard requires that shared_ptr use some SFINAE tricks to make sure that the template constructor only matches types that actually can be converted.

    The signature is (see section [util.smartptr.shared.const]):

    shared_ptr<T>::shared_ptr(const shared_ptr<T>& r) noexcept;
    template<class Y> shared_ptr<T>::shared_ptr(const shared_ptr<Y>& r) noexcept;
    

    Requires: The second constructor shall not participate in the overload resolution unless Y* is implicitly convertible to T*.

    Possibly the library hasn't yet been updated to comply with that requirement. You might try a newer version of libc++.

    Boost won't work, because it's missing that requirement.

    Here's a simpler test case: http://ideone.com/v4boA (This test case will fail on a conforming compiler, if it compiles successfully, it means the original case will be incorrectly reported as ambiguous.)

    VC++ 2010 gets it right (for std::shared_ptr).

    0 讨论(0)
提交回复
热议问题