18

I have just got the following warning from clang-tidy:

overloaded "operator++" returns a non-constant object 
 instead of a constant object type

https://clang.llvm.org/extra/clang-tidy/checks/cert-dcl21-cpp.html

Unfortunately the link which they are providing there does not work and https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682 has no easy way to find exactly this rule (seemingly the DCL rules start from 50).

But regardless where I look in the standard (for ex 16.5.7 Increment and decrement [over.inc]), I find no reference that postfix operator ++ should return a const:

struct X {
    X operator++(int); // postfix a++
};

Question: is just clang-tidy overly protective, erroneous or why would I want to declare the return type of the postfix to be const?

Useless
  • 64,155
  • 6
  • 88
  • 132
Ferenc Deak
  • 34,348
  • 17
  • 99
  • 167
  • Note: I logged a bug for this in the past, no reaction yet: https://bugs.llvm.org/show_bug.cgi?id=41842 – JVApen Jul 20 '19 at 21:33

1 Answers1

26

It's clang-tidy trying to stop you from writing code that accomplishes nothing:

(x++)++; // Did we just increment a temporary?

Such forms of overloading may be useful, but not usually for postfix ++. You have two options:

  1. Do as clang-tidy says, but then maybe lose the benfeits of move semantics.

  2. lvalue ref-qualify the overload instead, to mimic the little ints.

    X operator++(int) &; // Can't apply to rvalues anymore.
    

Option 2 is superior; prevents those silly mistakes, and retains move semantics if applicable.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    Oddly, Carnegie-Mellon seem to have changed their mind about this guideline, since it no longer exists [here](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682). – Useless Oct 18 '18 at 09:38
  • 1
    @Useless - In C++03 that's the only way to prevent this mistake (and there are no move semantics to worry about). I guess they updated it to be with accordance with contemporary C++? – StoryTeller - Unslander Monica Oct 18 '18 at 09:41
  • 2
    Probably. It's a pity they chose to break all the incoming links rather than leaving a note to that effect. – Useless Oct 18 '18 at 09:43
  • I wanted to say option 2 breaks `foo(returnsX()++);`, but then it feels kinda like a long shot. – Passer By Oct 18 '18 at 10:00
  • 2
    @PasserBy - It should break. Assuming `X++` behaves as expected, and returns a copy of the old value, it compiles, but is broken already. `foo` doesn't see the updated value. – StoryTeller - Unslander Monica Oct 18 '18 at 10:32
  • I applied option 2 in C++11, but clang-tidy still complains! – Sergey Kolesnik Dec 08 '20 at 08:08
  • 1
    @SergeyKolesnik - Of course it still complains. Option 1 is **to do as clang-tidy says** to blindly follow DCL21-CPP. Option 2 is not to do it. – StoryTeller - Unslander Monica Dec 08 '20 at 08:35
  • 4
    @StoryTeller-UnslanderMonica I think it would be helpful if you'd mentioned that in the answer. – Sergey Kolesnik Dec 08 '20 at 08:42
  • The best option here is to disable this obsolete rule in your clang-tidy config. Trying to follow it will likely trigger other contradictory clang-tidy rules. – metal Jan 23 '23 at 21:12