-1

How do I overload the increment operator so that this code becomes invalid -

Point p(2, 3);
++++p;

while allowing the following -

Point p(2, 3), a(0, 0), b(1, 4);
a = ++p + b;

Like in C this would be invalid -

int a = 2;
++++a;
  • 2
    *How do I overload the increment operator so that this code becomes invalid* -- I will be honest with you -- is it this important to make sure a crazy C++ programmer won't write crazy code? Whatever you come up with, a C++ programmer will bypass it with code that will be even crazier. – PaulMcKenzie Jul 18 '22 at 03:52
  • I've never seen "++++"-anything before. Why is it important to prohibit this behavior? – Dimitrije Kostic Jul 18 '22 at 03:53
  • @DimitrijeKostic I just want it to resemble C. If there's no way to achieve it then I guess that's ok. But it's just a curiosity of mine – Irtiaz Kabir Jul 18 '22 at 03:56
  • @IrtiazKabir If `operator++` is overloaded for your `Point` class (i.e., if `++p` is meaningful) then it seems neither possible nor reasonable to stop someone from applying that operator twice. – Dimitrije Kostic Jul 18 '22 at 03:59
  • @DimitrijeKostic ++ an int is meaningful as well. But why isn't ++++ int meaningful then? If `int` is expressing this behavior then why not `Point` ? – Irtiaz Kabir Jul 18 '22 at 04:01
  • @IrtiazKabir `++++i` where `i` is an `int` will compile just fine in C++. See [demo](https://onlinegdb.com/pMuxT3KQf). Additionally, why do you want it to resemble `C` ? In particular, in `C++` `++++i` is compilable. – Jason Jul 18 '22 at 04:03
  • @AnoopRana in C it doesn't – Irtiaz Kabir Jul 18 '22 at 04:05
  • @AnoopRana `++++i;` is OK in C++ but ***not in C***. – Adrian Mole Jul 18 '22 at 04:05
  • 1
    @IrtiazKabir Why do you want it to resemble C instead of C++? In C++, `++++a` is valid. If one is writing C++, one should try writing C++ not C. – Jason Jul 18 '22 at 04:09
  • *Why* the OP wants to do this is not really an issue, IMHO. The fact that they ***do*** want to do it but don't know how, makes this a perfectly valid question for Stack Overflow. My answer may not be the best approach, but it is one possible avenue for the OP to explore. – Adrian Mole Jul 18 '22 at 04:11
  • @IrtiazKabir -- Maybe the entire issue is that C++ allows operator overloading -- that concept does not exist in `C`. The `++` behavior is baked into C, and there is no flexibility, while in C++, an overloaded `operator ++` is an actual function, complete with return types, and if some programmer feels like it, have side effects. You are trying to control what comes naturally to C++ and operator overloading. – PaulMcKenzie Jul 18 '22 at 04:17
  • 1
    @AnoopRana Being related is not the qualification for a dupe target. Duping is also not the correct vector for giving advice. – Passer By Jul 18 '22 at 04:28
  • `++++a` is only allowed in C++ with overloaded `operator++()` functions (so disallowed for basic types like `int`). I recall a paper (will try to find a reference) that said chaining of overloaded `operator++()` is allowed in C++ because (1) a lot of other consequential changes needed to prevent it and keep the language consistent (2) such hacks rarely used outside obfuscated coding contests, and (3) it sucks for readability but actually isn't particularly harmful. (i.e. a lot of work to prevent for not much real-world benefit) I suspect the same would apply in writing C++ code to prevent it. – Peter Jul 18 '22 at 07:55
  • In C++, defensive programming protects you from Murphy, but not from Machiavelli. – Eljay Jul 18 '22 at 11:46

1 Answers1

1

One way you could do this is to make your operator++() return a const reference. That would prevent subsequent modification of the returned value, as in a 'chained' ++++p;.

Here's an outline version that also includes the required binary addition operator, implemented as a non-member function (as is normal):

#include <iostream>

class Point {
public:
    int x{ 0 }, y{ 0 };
    Point(int a, int b) : x{ a }, y{ b } {}
    const Point& operator++() { ++x; ++y; return *this; }
    Point& operator+=(const Point& rhs) { x += rhs.x; y += rhs.y; return *this; }
};

inline Point operator+(Point lhs, const Point& rhs)
{
    lhs += rhs;
    return lhs;
}

int main()
{
    Point p(2, 3), a(0, 0), b(1, 4);
    a = ++p + b; // OK: The result of the ++p is passed by value (i.e. a copy)
    std::cout << a.x << " " << a.y << "\n";
//  ++++a; // error C2678: binary '++': no operator found which takes a left-hand operand of type 'const Point'
    return 0;
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • One thing is that a reference to a local variable is being returned and that's not a big deal.. The program crashes for some reason – Irtiaz Kabir Jul 18 '22 at 04:15
  • 1
    @IrtiazKabir Oops - fixed (for now) by returning by value. Will investigate better options ... – Adrian Mole Jul 18 '22 at 04:16
  • @IrtiazKabir Does it still crash with the dangling reference issue fixed? I get an output of `4 8`, as expected ... and no warnings from clang-cl or MSVC, or their code analyzers. – Adrian Mole Jul 18 '22 at 04:19
  • No now it's fine – Irtiaz Kabir Jul 18 '22 at 04:22
  • Returning a `const` reference from `operator++()` would not necessarily prevent something like `a = ++p + b;` from working. For `a = ++p + b` to be broken, there would also need to be an `operator+()` that accepts a non-const first argument (e.g. a non-member overload of`operator+(P &p, const B &b)`). The bigger problem would be that returning a `const` reference from `operator++()` potentially breaks more than chaining of `++` (e.g. it can break things other than `++++++p` in ways that will be a bit counter-intuitive) but would not break things consistently. – Peter Jul 18 '22 at 06:49
  • @Peter Yeah. I've changed my answer to use more idiomatic operators, which are fine with the `const& ++` operator. But the fact that the proposed solution may also break other things *may* even be what OP is looking for. The pre-increment in **C** returns an rvalue but trying to implement an rvalue-returning overload sounds a bit like a nightmare ... `const&` strikes me as a "reasonable compromise". – Adrian Mole Jul 18 '22 at 06:57