Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object rvalue propagation for member function calls

I have a struct F with a function foo that has different implementation whether F is a temporary or not

struct  F{
  void foo() &  { std::cout << "F::foo() &" << std::endl; }
  void foo() && { std::cout << "F::foo() &&" << std::endl; }
};

Another struct A has a copy of F and in its function bar calls F::foo. I want to use the correct version of F::foo(). Therefore the implementation is:

struct A{

  void bar() & {
    f.foo();
  }

  void bar() && {
    std::move(f).foo();
  }

  F f;
};

I'm wondering if I really have to provide two implementations of A::bar(). Isn't there a smart way to use std::forward to automatically decide which F::foo() should be used?


An attempt:

struct B{

  void bar() {
    std::forward<F>(f).foo();
  }
  
  F f;
};

However, this does not work. It calls F::foo() && every time.


Complete example

like image 561
tom Avatar asked Oct 14 '20 11:10

tom


2 Answers

You can use a non-member function template:

struct B{

  template<typename TB>
  friend void bar(TB&& self) {
    std::forward<TB>(self).f.foo();
  }
  
  F f;
};

Depending on other function parameters, you might want to restrict the type of TB such that is_base_of_v<B, remove_const_t<remove_reference_t<TB>>>.

like image 100
dyp Avatar answered Sep 19 '22 15:09

dyp


No, there is no shortcut available at this point and you will need to stick to the verbose version. But have a look at p0847, "Deducing this". Not sure what the status of this proposal is, however. From the abstract:

We propose a new mechanism for specifying or deducing the value category of an instance of a class. In other words, a way to tell from within a member function whether the object it’s invoked on is an lvalue or an rvalue, and whether it is const or volatile.

like image 40
lubgr Avatar answered Sep 21 '22 15:09

lubgr