【问题标题】:Whys is this call ambiguous? [duplicate]为什么这叫模棱两可? [复制]
【发布时间】:2021-11-28 07:05:55
【问题描述】:

在下面的代码中,为什么对bar(std::shared_ptr<B>)的调用是模棱两可的,而bar(std::shared_ptr<A>)却不是?

foo 的目的是区别对待 const 和非 const 指针。除了将呼叫站点更改为 bar(std::dynamic_pointer_cast<A>(b)) 之外,我可以通过其他任何方式来消除歧义吗?

#include <memory>

struct A {};
struct B : A {};


void foo(std::shared_ptr<const A>) { }
void foo(std::shared_ptr<A>) { }

void bar(const A &) { }
void bar(A &) { }

int main() {
    A a;
    bar(a); // ok

    B b;
    bar(b); // ok

    auto ap = std::make_shared<A>();
    foo(ap); // ok

    auto bp = std::make_shared<B>();
    foo(bp); // ambiguous

    return 0;
}

【问题讨论】:

  • A void foo(std::shared_ptr&lt;A&gt;) 将共享 所有权 传递给 foo 例程。如果意图是通过共享所有权,那么这是正确的做法。如果传递所有权不是意图,那么参数应该是AA*A const*A&amp;A const&amp;

标签: c++ overload-resolution


【解决方案1】:

调用不明确,因为 std::shared_ptr&lt;B&gt; 不是 A 类型的 const 或非 const 共享指针。

因此,它将使用从std::shared_ptr&lt;B&gt;std::shared_ptr&lt;A&gt;std::shared_ptr&lt;const A&gt; 的隐式转换操作。这两个选项都是模棱两可的,因为您总是可以从非 const 转换为 const。

如果你有:

auto bp = std::make_shared<const B>();
foo(bp);

它不再模棱两可,因为在这种情况下,const B 只能转换为 const A

由于隐式转换不明确,因此您必须在给定场景中使用显式转换。

作为 hack,您可以编写一些帮助模板,它会自动检测给定指针是否为 const 并自动通过显式转换传递它。

template < typename T>  
void foo( std::shared_ptr<T>& ptr)
{
    foo( std::static_pointer_cast<A>(ptr) );
}

template < typename T>  
void foo( std::shared_ptr<const T>& ptr)
{
    foo( std::static_pointer_cast<const A>(ptr) );
}

现在你可以像这样使用它:

    auto bp = std::make_shared<B>();
    foo(bp); 
    auto bp2 = std::make_shared<const B>();
    foo(bp2); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 2018-06-01
    • 2011-08-01
    • 2018-05-28
    • 1970-01-01
    相关资源
    最近更新 更多