Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chain-calling member functions off a constructor of a named object

First, I'm NOT talking about c++11 constructor chaining aka constructor delegation.

Class member functions can return a reference to itself (the class) so function calls can be chained. (Such as how the cout << operator works to allow chain calls.)

When instantiating an anonymous object, such chain calls can occur off the constructor.

Can chain calls be made off a constructor of a named object? The lines for "foo a" and "foo b" below do not compile, so I'm wondering if there's a different syntax.

#include <iostream>
using namespace std;

class foo {
   public:
      foo(int x) : val{x} { };
      foo& inc() { ++val; return *this; }
      int getVal() { return val; };
   private:
      int val;
};

int main() {
   cout << foo(1).inc().getVal() << endl; // prints 2
   cout << foo{2}.inc().inc().inc().inc().getVal() << endl; // prints 6
   foo a(3).inc(); // error: expected ‘,’ or ‘;’ before ‘.’ token
   foo b{4}.inc(); // error: expected ‘,’ or ‘;’ before ‘.’ token
   cout << a.getVal() << endl;
   cout << b.getVal() << endl;
}
like image 710
user1902689 Avatar asked Sep 25 '16 01:09

user1902689


2 Answers

I think this is one of the advantages of the Almost Always Auto style. If you are in the habit of writing:

auto a = foo{3};

then you can chain calls without inconsistency:

auto a = foo{3}.inc();
like image 97
Chris Drew Avatar answered Oct 26 '22 06:10

Chris Drew


You can get a similar effect that chains the initialization:

foo c = foo{5}.inc().inc();

Surprisingly, my compiler optimized that to a constant, so there isn't a performance penalty.

like image 32
superscalar Avatar answered Oct 26 '22 05:10

superscalar