为什么这个调用有歧义?



在下面的代码中,为什么对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;
}

调用具有二义性,因为std::shared_ptr<B>不是a类型的const或非const共享指针。

因此,它将使用从std::shared_ptr<B>std::shared_ptr<A>std::shared_ptr<const A>的隐式强制转换操作。这两个选项都有歧义,因为总是可以从非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); 

最新更新