的C ++ 0x错误:超载STD功能:: shared_ptr的为const的说法是模糊 [英] C++0x Error: overloading a function with std::shared_ptr to const argument is ambiguous

查看:174
本文介绍了的C ++ 0x错误:超载STD功能:: shared_ptr的为const的说法是模糊的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个无关 A B 。我也有一个类布拉使用的boost :: shared_ptr的是这样的:

 类布拉{
上市:
    无效美孚(提高:: shared_ptr的<常量A>);
    无效美孚(提高:: shared_ptr的<常量B>);
}

注意在常量。这是此问题的原始版本缺乏重要组成部分。这将编译,下面code工作:

 喇嘛喇嘛;
提高:: shared_ptr的< A>一个;
bla.foo(一);

不过,如果我使用的boost :: shared_ptr的切换到使用的std :: shared_ptr的在上面的例子中,我得到一个编译错误,说:

 错误:重载呼叫'富(STD :: shared_ptr的< A>)'不明确
注意:考生:无效美孚(STD :: shared_ptr的<常量A>)
                      无效美孚(的std :: shared_ptr的<常量B>)

你能帮助我弄清楚为什么编译器无法弄清楚哪些功能在std :: shared_ptr的情况下使用,并能在升压:: shared_ptr的情况下?我使用的是默认的海湾合作​​委员会,并从Ubuntu 11.04的包库这是目前GCC 4.5.2版本的提升和Boost 1.42.0。

下面是完整的code,你可以尝试编译:

 的#include<升压/ shared_ptr.hpp>
使用boost :: shared_ptr的;
//#包括LT&;内存和GT;
//使用std :: shared_ptr的;A级{};
B类{};班布拉{
上市:
    无效美孚(shared_ptr的<常量A>){}
    无效美孚(shared_ptr的<常量B>){}
};诠释主(){
    喇嘛喇嘛;
    shared_ptr的< A>一个;    bla.foo(一);    返回0;
}

顺便说一句,这个问题促使我问<一个href=\"http://stackoverflow.com/questions/6322245/should-i-switch-from-using-boostshared-ptr-to-stdshared-ptr\">this问题我是否应该使用的std :: shared_ptr的都没有; - )


解决方案

的shared_ptr 有一个模板单参数的构造函数,这被认为是转换在这里。这就是让实际参数的shared_ptr&LT;衍生&GT; 来提供,其中一个的shared_ptr&LT;基本方式&gt;需要

由于两个的shared_ptr&LT;常量A&GT; 的shared_ptr&LT;常量B&GT; 有这样的隐式转换,这是不明确的。

至少有C ++ 0x中,该标准要求的shared_ptr 使用一些技巧SFINAE以确保该模板的构造函数只匹配,实际上可以转换的类型。

的签名(见 [util.smartptr.shared.const]

 的shared_ptr&LT; T&GT; :: shared_ptr的(常量的shared_ptr&LT; T&GT;&安培; R)noexcept;
模板&LT; Y类&GT; shared_ptr的&LT; T&GT; :: shared_ptr的(常量的shared_ptr&LT; Y&GT;&安培; R)noexcept;


  

要求:第二个构造不得参与重载决议,除非 Y * 隐式转换为 T *


也许库尚未更新,以符合这一要求。您可以尝试的libc ++的新版本。

加速将无法工作,因为缺少这一要求。

下面是一个简单的测试案例: http://ideone.com/v4boA (本测试案例都将失败一个符合标准的编译器,如果编译成功,就意味着原来的情况下将被错误地报告为不明确的。)

VC ++ 2010得到它的权利(对的std :: shared_ptr的)。

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

class Bla {
public:
    void foo(boost::shared_ptr<const A>);
    void foo(boost::shared_ptr<const B>);
}

Notice the const. That's the important part which the original version of this question lacked. This compiles, and the following code works:

Bla bla;
boost::shared_ptr<A> a;
bla.foo(a);

However, if I switch from using boost::shared_ptr to using std::shared_ptr in the above examples, I get a compilation error that says:

"error: call of overloaded 'foo(std::shared_ptr<A>)' is ambiguous
note: candidates are: void foo(std::shared_ptr<const A>)
                      void foo(std::shared_ptr<const B>)

Can you help me figure out why the compiler can't figure out which function to use in the std::shared_ptr case, and can in the boost::shared_ptr case? I'm using the default GCC and Boost versions from the Ubuntu 11.04 package repository which are currently GCC 4.5.2 and Boost 1.42.0.

Here is the full code that you can try compiling:

#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
// #include <memory>
// using std::shared_ptr;

class A {};
class B {};

class Bla {
public:
    void foo(shared_ptr<const A>) {}
    void foo(shared_ptr<const B>) {}
};

int main() {
    Bla bla;
    shared_ptr<A> a;

    bla.foo(a);

    return 0;
}

By the way, this issue motivated me to ask this question about whether I should be using std::shared_ptr at all yet ;-)

解决方案

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).

这篇关于的C ++ 0x错误:超载STD功能:: shared_ptr的为const的说法是模糊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆