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