Short version of the question
I ask for advice on whether to use. / * this versus β / this, i.e. C ++ (* this) .chained (). methods () compared to this-> clained () -> methods ().
By the way, at the moment, most of the pages I've seen recommend [[C ++ (* this) .chained (). Methods ()]].
I'm just curious because you can't do
My_Class object.chained (). methods ();
(By the way, I did not test the examples in this first section. I provide proven examples in the second section.)
You have to do
My_Class object,
object.chained () methods () ;.
which is an annoying extra line
Or you can do
My_Class object = My_Class().object.chained().methods();
which requires copying values ββis unacceptable if the constructor has side effects, for example, registering an instance of an object - like many Knobs libraries.
Or you can do
My_Class* object_ptr = *(new My_Class).object.chained().methods();
which works, but requires annoying * (ptr)
Or you can do
My_Class* object_ptr = (new My_Class)->object.chained()->methods();
which is best for teens.
I suppose you can do
my_class & object_ref (.. my_class () chain () methods ());
and I'm not sure what I think about it.
By the way, I don't need help for debugging here.
I program things like this all the time. I provide examples just for clarity.
I am looking for style tips because there are several ways to encode it, and I used different libraries that do this in reverse order.
And mixing them up is ugly:
My_Object_with_Setters* object_ptr2 = &((new My_Object_with_Setters)->set_R1(1).set_P1(2)->set_R1(3)) My_Object().method_returning_ptr()->method_returning_ref();
Maybe this is not so bad .... but it certainly can be confusing.
When I run code that uses two different libraries using the mixed methods .chained () -> () I sometimes want you to have postfix addresses and dereference operators
My_Object * mptr = My_Object (). Method_returning_ptr () β method_returning_ref β &
More complete examples
Setter functions
I most often use this idiom with setter functions
class My_Object_with_Setters { public: static int count; int value; public: My_Object_with_Setters() { ++count; value = 0; } public: std::ostream& print_to_stream(std::ostream& ostr) const { ostr << "(" << this->count << "," << this->value << ")"; return ostr; } friend std::ostream& operator<< ( std::ostream& ostr, const My_Object_with_Setters& obj ) { return obj.print_to_stream(ostr); } public: My_Object_with_Setters& set_R1(int val) { this->value = val; std::cout << "set_R1: " << *this << "\n"; return *this; } My_Object_with_Setters& set_R2(int val) { this->value = val; std::cout << "set_R2: " << *this << "\n"; return *this; } public: My_Object_with_Setters* set_P1(int val) { this->value = val; std::cout << "set_P1: " << *this << "\n"; return this; } My_Object_with_Setters* set_P2(int val) { this->value = val; std::cout << "set_P2: " << *this << "\n"; return this; } public: My_Object_with_Setters set_V1(int val) { this->value = val; std::cout << "set_V1: " << *this << "\n"; My_Object_with_Setters retval; retval = *this;
Test output:
cascading ref, ref, copy, copy, ref, ref set_R1: (1,1) set_R2: (1,2) set_V1: (1,11) set_V2: (2,12) set_R1: (3,101) set_R2: (3,102) cascading ptr, ptr, ptr, ptr set_P1: (4,1) set_P2: (4,2) set_P1: (4,11) set_P2: (4,12) cascading &address-of, ptr, ptr set_P1: (4,1) set_P2: (4,2) cascading new ptr ref ptr ref set_R1: (5,1) set_P1: (5,2) set_R1: (5,3)
General example
class My_Object { public: static int count; public: My_Object() { ++count; } public: My_Object& method1_returning_ref_to_current_object() { std::cout << count << ": method1_returning_ref_to_current_object\n"; return *this; } My_Object& method2_returning_ref_to_current_object() { std::cout << count << ": method2_returning_ref_to_current_object\n"; return *this; } public: My_Object* method1_returning_ptr_to_current_object() { std::cout << count << ": method1_returning_ptr_to_current_object\n"; return this; } My_Object* method2_returning_ptr_to_current_object() { std::cout << count << ": method2_returning_ptr_to_current_object\n"; return this; } public: My_Object method1_returning_value_copy_of_current_object() { std::cout << count << ": method1_returning_value_copy_of_current_object\n"; My_Object retval; return retval; } My_Object method2_returning_value_copy_of_current_object() { std::cout << count << ": method2_returning_value_copy_of_current_object\n"; My_Object retval; return *this; } }; int My_Object::count = 0;
Test output
cascading ref, ref, copy, copy, ref, ref 1: method1_returning_ref_to_current_object 1: method2_returning_ref_to_current_object 1: method1_returning_value_copy_of_current_object 2: method2_returning_value_copy_of_current_object 3: method1_returning_ref_to_current_object 3: method2_returning_ref_to_current_object cascading ptr, ptr, ptr, ptr 4: method1_returning_ptr_to_current_object 4: method2_returning_ptr_to_current_object 4: method1_returning_ptr_to_current_object 4: method2_returning_ptr_to_current_object cascading &address-of, ptr, ptr 4: method1_returning_ptr_to_current_object 4: method2_returning_ptr_to_current_object cascading new ptr ref ptr ref 5: method1_returning_ptr_to_current_object 5: method2_returning_ref_to_current_object
By the way, I don't need help for debugging here. I provide examples only for clarity.
I am looking for style tips.