user1641854
user1641854

Reputation:

perfect forwarding through base class

I want to be able to perfect forward argument to derived class through base class. The only idea I have is to implement not virtual perfect forwarding function in base class and have virtual functions overloads for lvalues and rvalues. Something like this:

Consider:

#include <iostream>
#include <memory>
#include <string>

class base_t
{
public:
    virtual ~base_t() = default;

    template<typename T>
    void perfect_forward(T&& value)
    {
        process(std::forward<T>(value));
    }

protected:
    virtual void process(const std::string& value) = 0;
    virtual void process(std::string&& value) = 0;
};

class derived_t : public base_t
{
protected:
    void process(const std::string& value) override final
    {
        std::cout << "derived_t::process(const lvalue&)" << std::endl;
    }

    void process(std::string&& value) override final
    {
        std::cout << "derived_t::process(rvalue&&)" << std::endl;
    }
};

int main(int argc, const char* argv[])
{
    const std::string lvalue;
    auto rvalue = []() { return std::string(); };

    std::unique_ptr<base_t> base(new derived_t);
    base->perfect_forward(lvalue);
    base->perfect_forward(rvalue());
}

But this has a little meaning, because instead of template perfect_forward function in base class I can simply provide two overload for virtual process. How I can avoid code duplicate in derived class for process method and use std::forward there through base_t interface?

Upvotes: 1

Views: 852

Answers (1)

Simple
Simple

Reputation: 14420

If you don't want to take the std::string by value, there is an approach using a mixin class, but it requires changing your class hierachy:

template<class D>
class process_mixin : public base_t {
protected:
    void process(std::string const& value) override final {
        return ((D*)this)->do_process(value);
    }

    void process(std::string&& value) override final {
        return ((D*)this)->do_process(std::move(value));
    }
};

class derived_t : public process_mixin<derived_t> {
protected:
    template<typename T>
    void do_process(T&& value) {
    }

    friend process_mixin<derived_t>;
};

process_mixin only has to be written once. From then on anything that derives from base_t can instead derive from process_mixin and you get a perfect forwarding interface.

Upvotes: 3

Related Questions