How to execute std :: forward (* this)

because I want to overload all the cv and reference qualifications of a member function, I wrote myself the following macro:

#define DEFINE_FUNCTION(sig , functionality) \ sig & { functionality; } \ sig && { functionality; } \ sig const & { functionality; } \ sig const && { functionality; } \ sig volatile & { functionality; } \ sig volatile && { functionality; } \ sig const volatile & { functionality; } \ sig const volatile && { functionality; } 

Unfortunately, if I want to return *this in redirection mode (which saves all references and the cv-qualification of this -pointer in the returned type, it seems I have to manually write all 8 of these overloads.

Now to my question: Is it possible to universally get the cv class and the qualified reference type *this ?

I tried decltype(auto) as return type and

 return std::forward<decltype(*this)>(*this); 

but apparently the resulting expression always resolves the lvalue reference even in the case of the && -qualified function.

Can you help me?

+5
source share
1 answer

You need a friend.

 struct blah { decltype(auto) foo() & { return do_foo(*this); } decltype(auto) foo() && { return do_foo(std::move(*this)); } decltype(auto) foo() const& { return do_foo(*this); } decltype(auto) foo() const&& { return do_foo(std::move(*this)); } decltype(auto) foo() const volatile& { return do_foo(*this); } decltype(auto) foo() const volatile&& { return do_foo(std::move(*this)); } decltype(auto) foo() volatile& { return do_foo(*this); } decltype(auto) foo() volatile&& { return do_foo(std::move(*this)); } blah( const volatile blah&& b ) {} blah( const volatile blah& b ) {} blah( const blah& b ) = default; blah( blah&& b ) = default; blah() = default; template<class Self> friend blah do_foo(Self&& self) { std::cout << "Is reference:" << std::is_reference<Self>::value << "\n"; std::cout << "Is const:" << std::is_const<std::remove_reference_t<Self>>::value << "\n"; std::cout << "Is volatile:" << std::is_volatile<std::remove_reference_t<Self>>::value << "\n"; return decltype(self)(self); } }; 

test code:

 blah{}.foo(); blah tmp; tmp.foo(); const blah tmp2; tmp2.foo(); 

Output:

 Is reference:0 Is const:0 Is volatile:0 Is reference:1 Is const:0 Is volatile:0 Is reference:1 Is const:1 Is volatile:0 

Living example .

Use a macro to implement methods that are forwarded to a friend, and write each other manually. The methods that are passed to a friend may even be template<class...Args> if you are ok with the disadvantages of perfect forwarding.

You will have less of your code that works in a macro.

 #define RETURNS(...) \ noexcept(noexcept(__VA_ARGS__)) \ -> decltype( __VA_ARGS__ ) \ { return __VA_ARGS__; } #define FORWARD_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \ template<class...Args> auto NAME( Args&&... args ) REF_QUAL \ RETURNS( HELPER_NAME( SELF, std::forward<Args>(args)... ) ) #define FORWARD_CV_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \ FORWARD_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \ FORWARD_METHOD_TO_FRIEND( NAME, SELF, const REF_QUAL, HELPER_NAME ) \ FORWARD_METHOD_TO_FRIEND( NAME, SELF, const volatile REF_QUAL, HELPER_NAME ) \ FORWARD_METHOD_TO_FRIEND( NAME, SELF, volatile REF_QUAL, HELPER_NAME ) #define FORWARD_SELF_TO_FRIEND( NAME, HELPER_NAME ) \ FORWARD_CV_METHOD_TO_FRIEND( NAME, *this, &, HELPER_NAME ) \ FORWARD_CV_METHOD_TO_FRIEND( NAME, std::move(*this), &&, HELPER_NAME ) 

which shortens blah to:

 struct blah { FORWARD_SELF_TO_FRIEND( foo, do_foo ) // ... template<class Self> void do_foo( Self&& self ) { // some_blah.foo() invokes do_foo passing it // self with the proper qualifications } }; 

replaces (and improves) all foo() methods.

some_blah.foo() now calls do_foo( some_blah ) with the proper CV and L / R qualifications and noexcept on some_blah .

constexpr may take some love to get right, because we don't have a constexpr conditional test in C ++ right now. Perhaps the simple constexpr statement in the foo template is generated correctly, but I am foggy on this.

+5
source

Source: https://habr.com/ru/post/1273147/


All Articles