【问题标题】:How to write operator== to work with implicitly casted/constructed types如何编写 operator== 以使用隐式转换/构造类型
【发布时间】:2018-07-20 02:21:13
【问题描述】:

为什么这不起作用,因为有一个隐式“构造”选项?

class A {};

template<typename T>
class Type {

public:
    Type() = default;
    Type(T* ptr) {
    }
};

template<typename T>
bool operator==(Type<T> l, Type<T> r) {
    return true;
}

int main() {
    A a;
    Type<A> type(&a);
    bool v = (type == &a); // Does not work
    //bool v = (type == Type<A>(&a)); // That would work
}

为什么不使用带有(&amp;base,即A*)的隐式构造Type&lt;A&gt;?

我怎样才能编写此代码以使其工作?

【问题讨论】:

  • 您可能需要使用类似:template&lt;typename T, typename U&gt; bool operator==(Type&lt;T&gt; l, Type&lt;U&gt; r).

标签: c++ oop templates operator-overloading


【解决方案1】:

在检查函数模板的可行性时,不考虑用户定义的转换。

在检查函数模板的可行性时,实现会尝试根据模板参数推导规则来推导模板参数。这些规则不涉及任何类型转换(仅类型调整,如删除限定符和引用)。如果扣除失败,候选人将被拒绝。

在您的情况下,T 不能从 Type&lt;A&gt; 和 A 推导出来。您需要两个参数具有相同的类型 Type&lt;X&gt; 才能成功推导。

【讨论】:

  • “在检查功能模板的可行性时不考虑用户定义的转换”是否是 SFINAE 在稍后(可能)应用之前将这些候选者从运行中剔除的结果?
  • @Eljay 我想你可以用这些术语来说明它。 SFINAE从来不是标准采用的官方术语,只是理解模板参数推导的方便助记词。
【解决方案2】:

你可以让操作符在你的类Type中重载一个友元函数:

template<typename T>
class Type {

public:
    Type() = default;
    Type(T* ptr) {
    }

    inline friend bool operator==(Type<T> l, Type<T> r) {
        return true;
    }
};

这可确保从您声明变量Type&lt;A&gt; type; 的那一刻起实际实例化运算符。

在您的情况下,它没有被实例化。编译器可以在您调用运算符时创建模板的实例,但它会失败,因为模板运算符声明无法推断出参数Type&lt;A&gt; 和A*。这实际上是您收到的错误消息:

错误:'operator==' 不匹配(操作数类型为 'Type' 和 'A*')

因此,甚至不考虑 Type&lt;A&gt; 的隐式构造,因为此时不存在具有签名 bool operator==(Type&lt;A&gt; l, Type&lt;A&gt; r) 的函数。

【讨论】:

  • 非常好。您可以省略&lt;T&gt;,也可以将其声明为operator==(Type l, Type r)。
  • @super 哦有趣,我没有意识到这会起作用!
  • 嗯.. 很奇怪,但是.. 有效:p 我仍然不完全理解它不能“正常”工作的原因。编译器声称它可以看到这个函数:jdoodle.cpp:17:6: note: Candidate: template bool operator==(Type, Type) bool operator==(Type l, Type r) { ^~~~~~~~ jdoodle.cpp:17:6: 注意: 模板参数推导/替换失败: jdoodle.cpp:27:16: 注意: 类型不匹配'Type' 和 'A*' 我什至尝试使用类型 A 显式实例化此 operator==,但仍然 - 没有帮助..
【解决方案3】:

您可以定义以下附加功能模板:

template<typename T>
bool operator==(Type<T> l, T* r) {
    return l == Type<T>{r};
}

这个函数模板的主体显式构造你的函数模板需要的Type&lt;T&gt;对象,以便正确推导出T,以便它可以被实例化。

这样,type == &amp;a 将导致调用此函数模板的实例化,进而调用函数模板的实例化bool operator==(Type&lt;T&gt; l, Type&lt;T&gt; r)。

【讨论】:

  • 是的,但是过多的重载运算符会产生其他问题:p
【解决方案4】:

好吧,编译器错误状态:

错误:'operator==' 不匹配(操作数类型为 'Type' 和 'A*')

并且您对两个参数都使用 typename T,但由于类型不匹配,因此无法正常工作。

也考虑使用这样的东西:

template<typename T, typename U> 
bool operator==(Type<T> l, U r)
{
    return true;
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2021-10-16
相关资源
最近更新 更多