重载运算符++前缀/后缀互相影响吗?

发布于 2024-09-09 04:42:45 字数 1726 浏览 1 评论 0原文

我有一个问题,以前可能已经被回答了 9000 多次,但我真的不知道如何表达,这就是我要尝试的。

我在一些 C++ 书籍和教程中看到,当定义自己的具有可迭代值(可递增)语义的类时,您可以为其重载 operator++ (我将在这里声明我的所有内容) d 猜测也适用于operator--)。执行此操作的标准方法似乎是:

class MyClass {
    public:
    MyClass& operator++ () {
        increment_somehow();
        return *this;
        }
    ....
    };

其中 increment_somehow() 好吧...以某种方式递增对象的值。

然后,可以以如下方式定义 operator++ 的后缀版本:

MyClass operator++ (MyClass& it, int dummy) {
    MyClass copy(it);
    ++it;
    return copy;
    }

It is all Fine and dandy(我想我的习惯用语是对的),但问题是,做这一切是为了每个定义 operator++ 的类很快就会变得令人厌烦和冗长,所以我想我可以利用我最近在重载运算符时学到的一个技巧。也就是说,利用 头文件和一个名为 rel_ops 的工具,这是我昨天发现的(我在 4 年后才回到 C++) 离开多年...):(

class MyClass {
    public:
    bool operator== (const MyClass& that) {
        return compare_for_equality_somehow(that);
        }
    bool operator< (const MyClass& that) {
        return compare_for_lessality_somehow(that);
        }
    ....
    using namespace std::rel_ops; // operators >, >=, <=, ! are "magically" defined!
    };

出于类比目的,我刚刚发明了术语“lessality”,出于某种原因,我的头脑拒绝想出正确的数学术语...)

我创建了一个简单的标题 < code>其内容在某种程度上模仿了 Utility 标头中的 std::rel_ops 命名空间。据我在几次编译后所看到的,它就可以工作了(TM)。我可以/我应该使用这个技巧吗?如果我创建一个类并使用 using namespace MyLibrary::increment_operators (例如),可能会遇到哪些陷阱?

也许更重要的是:我是否再次重新发明了轮子,或者我刚刚创建了一个可以聚合到此类项目的有用的小型库?几乎所有我尝试用 C++ 进行的让自己恢复最新状态并进行协作的实验似乎都已包含在 boost::do_something 工具中,这让我有点难过我已经离开了这么多时间。

I have a question that may have been answered over 9000 times before but I really don't know how to word it, this is what I am going to try.

I've seen in some C++ books and tutorials that when defining your own class which has a iterable value (incrementable) semantics, you can overload operator++ for it (all I'm going t state here I'd guess applies for operator-- as well). The standard way of doing this seems to be:

class MyClass {
    public:
    MyClass& operator++ () {
        increment_somehow();
        return *this;
        }
    ....
    };

Where increment_somehow() well... somehow increments the object's value.

Then, it is possible to define the postfix version of operator++ in a manner like this:

MyClass operator++ (MyClass& it, int dummy) {
    MyClass copy(it);
    ++it;
    return copy;
    }

It is all fine and dandy (I think I got that idiom right), but the problem is that doing all that for each class that defines operator++ quickly becomes tiresome and verbose, so I was thinking that I could take some advantage of a trick that I recently learnt when overloading operators. That is, making use of the <utility> header and a facility inside called rel_ops that I found out about yesterday (I just came back to C++ after four years of being away...):

class MyClass {
    public:
    bool operator== (const MyClass& that) {
        return compare_for_equality_somehow(that);
        }
    bool operator< (const MyClass& that) {
        return compare_for_lessality_somehow(that);
        }
    ....
    using namespace std::rel_ops; // operators >, >=, <=, ! are "magically" defined!
    };

(I just invented the term "lessality" for analogy purposes, my head refuses to come up with the correct mathematical term for some reason...)

I created a simple header <step_ops.hpp> whose content somewhat imitates the std::rel_ops namespace found in the Utility header. Fro what I can see after a couple of compiles, it just works(TM). Can I / Should I use this trick? What are possible pitfalls I could come up against if I create a class and use a using namespace MyLibrary::increment_operators (for example)?

And maybe much, MUCH more important: Have I just reinvented the wheel again, or have I just created a useful small library that could be aggregated to such kinds of projects? Pretty much any experiments that I have tried to do with C++ to get myself back up-to-speed and collaborate stuff seem to already be covered under a boost::do_something facility and it makes me kind of sad that I have spent so much time away.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江心雾 2024-09-16 04:42:45

Boost 在 Boost Operators 实用程序库中提供了此功能。它的实现有点不同,但达到了相同的结果。

我可以/我应该使用这个技巧吗?

尽可能使用它;删除冗余和重复的代码是重构的基本原则,也是一个很好的实践。

我是否再次重新发明了轮子,或者我刚刚创建了一个可以聚合到此类项目的有用的小型库?

我想你可能会说你重新发明了轮子。不过,我认为这不一定是一件坏事:我发现,如果我自己实现一些东西,我通常会更好地理解它,并在这个过程中学到很多东西。

Boost provides this functionality in the Boost Operators utility library. Its implementation is a little different, but achieves the same result.

Can I / Should I use this trick?

Use it wherever you can; cutting out redundant and repetitive code is a fundamental principle of refactoring and is a good practice to get into.

Have I just reinvented the wheel again, or have I just created a useful small library that could be aggregated to such kinds of projects?

I guess you could say then that you've reinvented the wheel. I don't think that's necessarily a bad thing, though: I find that if I implement something myself I usually understand it much better and learn a lot through the process.

沫尐诺 2024-09-16 04:42:45

如果您有空闲时间并且需要经验,请重新发明您喜欢的所有轮子。我自己也做了一些,以提高我对基本概念的了解。它可以有很大帮助。

If you've got the time to spare, and need the experience, reinvent all the wheels you like. I've done several myself, to improve my knowledge of the underlying concepts. It can help a lot.

青萝楚歌 2024-09-16 04:42:45

Alternatively you could use <template T> it is built right into the c++ language, it allows you to use multiple types for the same code, all you need to do is make sure that for each class there that uses the newly defined operator with class template all methods are defined.

See the documentation for more info about template http://www.cplusplus.com/doc/tutorial/templates/

安静 2024-09-16 04:42:45

我是原发帖者,只是回答说我终于注册了 StackOverflow。这样我就有了一个新的手柄。现在感谢大家的回答,特别是 HeadGeek 的动机问题。另外,为了纠正自己并遵循 tjm 的评论,代码使用的确切形式并不像我发布的那样。使用此方法的更正确方法是通过 using 将每个运算符带入类自己的作用域:

namespace scope {
class MyClass {
  public:
  bool operator== (const MyClass& that) {
    return compare_for_equality_somehow(that);
    }
  bool operator< (const MyClass& that) {
    return compare_for_lessality_somehow(that);
    }
  ....
  // using namespace std::rel_ops; // that one is incorrect
  };
using std::rel_ops::operator=!; // similarly for >, >=, <=
} // end of namespace

如果按照我原来的帖子中的方式完成,则标头可以正常编译,但是当标头被包含在一个项目中,该项目也包含并在某处使用 rel_ops 。更重要的是,该方法将为类范围内定义的所有类带来所有运算符——这绝对是不可取的。通过这种显式using方法,只有所需的运算符才会被纳入范围,并根据需要解析它们。

谢谢大家,很快再见。

另外,请不要对这个问题投赞成票,除非您真的觉得它有什么可提供的 - 这不是什么新鲜事,因为 Boost 已经有了它 - 我发布此问题是出于双重信息目的

I'm the original poster, just answering to say that I finally registered to StackOverflow. As such I have a new handle. Now saying thanks to the answers, in particular HeadGeek with the motivation issue. Also, to correct myself and folloiwing on tjm's comment, the exact form the code is used is not as I posted. The more correct way of using this method is to bring each operator into the class's own scope via using:

namespace scope {
class MyClass {
  public:
  bool operator== (const MyClass& that) {
    return compare_for_equality_somehow(that);
    }
  bool operator< (const MyClass& that) {
    return compare_for_lessality_somehow(that);
    }
  ....
  // using namespace std::rel_ops; // that one is incorrect
  };
using std::rel_ops::operator=!; // similarly for >, >=, <=
} // end of namespace

If done as in my original post, the header compiles fine, but compilation errors are brought when the header is included in a project that also includes and uses rel_ops somewhere. More importantly, that method would bring all operators for all classes defined in the class's scope -- definitively not desirable. With this approach of explicitly using, only the needed operators are brought into scope, and they are resolved as needed.

Thanks everyone, seeing you soon.

(Also, please, don't upvote this question unless you really feel it has something to offer -- it is nothing new since Boost already has it -- I posted this for dual informative purposes)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文