Home > database >  C Perfect Forwarding function
C Perfect Forwarding function

Time:12-22

I've read about perfect forwarding, but still I've got questions)

Consider this code


template<typename Input , typename Output>
struct Processor 
{
    Output process(Input&& input)
    {
        startTimer(); // Starting timer
        auto data = onProcess(std::forward<Input>(input)); // Some heavy work here
        stopTimer(); // Stopping timer
        logTimer(); // Logging how many ms have passed
        return data;
    }

protected:
    Output onProcess(Input&& input) = 0; // one overload for rvalue-references
    Output onProcess(const Input& input) = 0; // one overload for const lvalue-references
};

My problem is that onProcess(Input&& input) and onProcess(const Input& input) will always do the same. How can I have one overload for both const lvalue reference and rvalue reference, will having one const lvalue reference cost me memory and performance? Also what if I had an overload with onProcess(Input& input) how could I solve my problem then?

UPDATE

My example was not using perfect forwarding, so I've corrected it for the right context of the question

template<typename Input , typename Output>
struct Processor 
{

    template<class I, 
    std::enable_if_t<std::is_same_v<std::decay_t<I>, Input>, int>=0>
    Output process(I&& input)
    {
        startTimer(); // Starting timer
        auto data = onProcess(std::forward<I>(input));
        stopTimer(); // Stopping timer
        logTimer(); // Logging how many ms have passed
        return data;
    }
protected:
    Output onProcess(Input&& input) = 0; // one overload for rvalue-references
    Output onProcess(const Input& input) = 0; // one overload for const lvalue-references
};

CodePudding user response:

Perfect forwarding is possible when you have a forwarding reference.

Example:

template<class I, std::enable_if_t<std::is_convertible_v<I, Input>, int> = 0>
Output process(I&& input)
{
    startTimer(); // Starting timer
    auto data = onProcess(std::forward<I>(input));
    stopTimer(); // Stopping timer
    logTimer(); // Logging how many ms have passed
    return data;
}

As for the virtual function onProcess, you can't have a similar construct there since virtual functions can't be function templates. Since both overloads are supposed to do the same thing without changing the object, only make one of those functions and take the Intput by const&.

  • Related