0

I have a generic code at which point I leave a possibility to modify data.

if (impl_.mode() == implementation_type::manual)
{
    const auto steering = custom::customize_steering(impl_, input.steering());
    impl_.output_interface()(steering);
    return impl_.do_continue(impl_.params().period());
}

By default I want customize_steering to be optimized out.
Now I have it this way:

template<typename ImplT, typename SteeringT>
constexpr std::decay_t<SteeringT> customize_steering(ImplT &, SteeringT &&steering)
{
   return std::forward<SteeringT>(steering);
}

Is it the right way to do or is it too convoluted and passing by const reference will do fine?


I decided to check, and I don't get the results I expect.

#include <iostream>

class foo
{
public:
    foo() { std::cout << "Constructed" << std::endl; }

    foo(const foo &) { std::cout << "Copy constructed" << std::endl; }

    foo(foo &&) { std::cout << "Move constructed" << std::endl; }

    ~foo() { std::cout << "Destroyed" << std::endl; }
};

template<typename T>
std::decay_t<T> do_nothing(T &&t)
{
        return std::forward<T>(t);
//    return t;
}

int main(int, char **)
{
    const auto &fcr = do_nothing(do_nothing(do_nothing(foo())));
    const auto fc = do_nothing(fcr);

    return 0;
}

The output is (MinGW64):

Constructed
Move constructed
Move constructed
Move constructed
Destroyed
Destroyed
Destroyed
Copy constructed
Destroyed
Destroyed

What I expected:

  1. Without mandatory copy elision: Constructor -> Move constructor.
  2. With mandatory copy elision (C++17): Constructor (for const auto fc).

How can I make it work?

Sergey Kolesnik
  • 3,009
  • 1
  • 8
  • 28
  • Seems to me that `input.steering()` will produce a prvalue, so turning it into a const reference ends up with a useless copy being made. – Sam Varshavchik Jul 21 '21 at 13:43
  • @SamVarshavchik and what about a case when something other than prvalue is passed? – Sergey Kolesnik Jul 21 '21 at 13:45
  • `const auto steering =` forces to construct a object, even for identity operation... `const auto&` would be fine (and extend lifetime for temporary). – Jarod42 Jul 21 '21 at 13:48
  • @Jarod42 the intention is to construct it directly from `input.steering()` when no template specialization was made. – Sergey Kolesnik Jul 21 '21 at 13:49
  • @Jarod42 I assume that `const auto&` would not be fine if a template specialization makes a copy of `steering.input()` and returns it. Wouldn't it be a dangling reference then? – Sergey Kolesnik Jul 21 '21 at 13:52
  • As I said, `const auto&` extends lifetime of temporary, and in case of customization which is identity (and not copy as you do), it avoid all copies. – Jarod42 Jul 21 '21 at 14:00
  • No, [it would not be a dangling reference](https://stackoverflow.com/questions/50673255/when-is-temporary-lifetime-extension-useful-in-modern-c). – Sam Varshavchik Jul 21 '21 at 14:00
  • @SamVarshavchik and what about the function signature? Is it valid in this case? – Sergey Kolesnik Jul 21 '21 at 14:05

0 Answers0