【问题标题】:Function call ambiguity (user-defined conversion and Derived2Base pointer conversion)函数调用歧义(自定义转换和 Derived2Base 指针转换)
【发布时间】:2019-08-29 19:37:02
【问题描述】:

下面代码中函数调用出现歧义的原因是什么?

我知道这里有两个可行的函数,正如编译器在 ERROR 消息中所说的那样(如下所示)

1) candidate: operator==(Base*, Base*)

-> 第一个参数需要用户定义从SmartPtrBase* 的转换

-> 需要 Derived*Base* 隐式 (?) 转换

2)candidate: bool operator==(const SmartPtr&, const Base*)

-> 需要为第一个参数添加顶级 const(精确匹配)

-> 需要 Derived*Base* 隐式 (?) 转换

从上面很明显,SmartPtr 内部定义的operator== 是更好的匹配(考虑到第一个参数和第二个参数相同)

代码

#include <iostream>

using namespace std;

template<class T> class SmartPtr
{
    public:

    operator T*() { return pointee__;}

    inline friend bool operator==(const SmartPtr& lhs, const T* rhs){
        return lhs.pointee__ == rhs;
    }

    private:

    T* pointee__;
};

struct Base{};

class Derived:public Base{};

int main()
{
    SmartPtr<Base> sp;
    Derived * dp;

    cout<<"Hello World"<< (sp==dp);

    return 0;
}

错误

main.cpp: In function ‘int main()’:
main.cpp:38:30: error: ambiguous overload for ‘operator==’ (operand types are ‘SmartPtr’ and ‘Derived*’)
     cout<<"Hello World"<< (sp==dp);
                            ~~^~~~
main.cpp:38:30: note: candidate: operator==(Base*, Base*) 
main.cpp:19:24: note: candidate: bool operator==(const SmartPtr&, const Base*)
     inline friend bool operator==(const SmartPtr& lhs, const T* rhs){
                        ^~~~~~~~

谢谢!

【问题讨论】:

  • 我建议阅读this
  • 这并没有解决问题,但包含两个连续下划线 (pointer__) 的名称和以下划线后跟大写字母的名称保留供实现使用。不要在你的代码中使用它们。

标签: c++ c++11


【解决方案1】:

从上面很明显,在 SmartPtr 中定义的 operator== 是更好的匹配(考虑到第一个参数)

不完全是:第一个转换为SmartPtr &amp;SmartPtr const &amp;

第二个需要两次转换:

1) 从Derived *Base *

2) 从Base *Base const *

如果你定义

Derived * dp;

指向const的指针

Derived const * dp;

歧义消失,代码编译。

如果你定义spconst也是一样

SmartPtr<Base> const sp{};

如果您修改SmartPtr 中的operator==() 以接受Base *(不是Base const *)作为第二个参数,也会消失。

【讨论】:

  • 我怎么错过了const 转换?!这就是为什么有时让别人看看你的代码是件好事。非常感谢!另外我猜你的意思是const Derived * dp 而不是Derived const * dp
  • 另一种解决方案是将函数模板化为template&lt;class U&gt; inline friend bool operator==(const SmartPtr&amp; lhs, const U* rhs){ return lhs.pointee__ == rhs; }
  • @User10482 - 规则是:const 应用于左边的元素;如果左侧没有元素,则将其应用于右侧的元素。所以const Derived *Derived const * 是同一件事:指向常量Derived 对象的可修改指针。不同的是Derived * const:一个指向可修改Derived对象的常量指针。
猜你喜欢
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多