【问题标题】:C++ Global Operator Overloading Design IssueC++ 全局运算符重载设计问题
【发布时间】:2022-01-21 19:58:21
【问题描述】:

我目前的设计有问题。

我有一个可以用任何 1 个参数构造的类。如果它在概念上有所帮助,请将 T 视为 lambda。

// 1
template<class T>
foo(T) {/*...*/}

这个类重载了很多操作符,比如!=

// 2
template<class T>
bool foo::operator!=(const T&) {/*...*/}

运算符独立于左右顺序,所以我在全局范围内定义了这个:

// 3
template<class T>
bool operator!=(T const& lhs, const foo& rhs) {return rhs != lhs;}

因此,我收到了很多模棱两可的operator!= 电话。这是因为它尝试使用3,将第二个参数转换为foo,因为它隐式接受所有参数,然后交换参数的顺序并调用成员函数。我以为通过向3 const&amp; 提出论点可以避免这种情况,但我错了。

我想出了几个选项,但我对其中任何一个都不满意。

  1. 使构造函数显式化(这会破坏 40% 的语法糖,即此类的目标)
  2. 删除全局运算符
  3. 将全局操作符放入命名空间,然后在需要的时候做using namespace

我还有哪些其他选择?

【问题讨论】:

  • 如果 &lt;&lt; 让你感到困惑,想象一下它会如何让任何使用你的代码的人感到困惑
  • 用明确的函数名替换操作符
  • @AlexeyLarionov 它既不会让我感到困惑,也不会让实现本身感到困惑。此外,我是唯一使用该代码的人。
  • @PepijnKramer 这是一个很好的选择。不幸的是,该类是一个语法糖类,仅此而已。添加显式函数实际上违背了类的目的。此外,operator+operator!= 等其他人也会发生这种情况。
  • 我已将帖子编辑为关于!=,因为这样可能更有意义。

标签: c++ c++17 operator-overloading


【解决方案1】:

你可能有一个小误解(或者我可能没有完全理解这个问题)

在您的比较功能中,您必须与Foo&lt;T&gt;&amp; 进行比较,而不是T&amp;

在你的全局函数中你需要一个不同的模板参数。一个用于您的 Foo 类,一个用于其他类型。

请看下面的代码示例。

请告诉我,这是否回答了您的问题,或者我是否需要添加更多内容。谢谢。

#include <iostream>

template <typename T>
class Foo {
    T t;
public:
    Foo(T x) : t(x) {}

    bool operator != (const Foo<T>& other) const { return t != other.t; }

    template <typename K>
    friend bool operator != (const K& k, const Foo<T>& other) { return k != other.t; }
};

int main() {
    Foo<int> foo1(42);
    Foo<int> foo2(43);

    int f = 43;

    if (foo1 != foo2)
        std::cout << "foo1 != foo2\n\n";
    else 
        std::cout << "foo1 == foo2\n\n";

    if (f != foo1)
        std::cout << "f != foo1\n\n";
    else
        std::cout << "f == foo1\n\n";

    if (foo2 != f)
        std::cout << "foo2 != f\n\n";
    else
        std::cout << "foo2 == f\n\n";
}

【讨论】:

  • foo 不是模板类,它是一个常规类。它旨在存储擦除类型的功能。它不能与其他 foo 对象进行比较,尽管它可以。它可用于与任何函数进行比较,并且它将比较函数是否运行相同,即使它们位于不同的内存区域中。 operator!= 不应将 rhs 转换为 foo,因为构建成本非常高。
猜你喜欢
  • 1970-01-01
  • 2011-06-29
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
相关资源
最近更新 更多