【问题标题】:perfect forwarding through base class通过基类完美转发
【发布时间】:2016-03-18 08:24:37
【问题描述】:

我希望能够通过基类完善前向参数到派生类。我唯一的想法是在基类中实现非虚拟完美转发功能,并为lvaluesrvalues 提供虚拟函数重载。像这样的:

考虑:

#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());
}

但这有点意思,因为我可以简单地为虚拟process 提供两个重载,而不是基类中的模板perfect_forward 函数。如何避免process 方法的派生类中的代码重复,并通过base_t 接口使用std::forward

【问题讨论】:

  • 如果您想要动态多态性,您将需要在某些时候进行虚拟调用,并且函数模板当然不能是虚拟的。你可以在derived_t 中有一个模板化的函数,它可以从派生类中的两个重载中调用。
  • 似乎在基类中为虚函数提供两个重载是最简单的方法:(
  • 你可以使用virtual void process(std::string value)
  • 简单,是的,但正如 Effective Modern C++ 在第 41 条中向我们学习的那样,这并不总是最佳选择。
  • “不总是最佳选择”是否意味着“从不”?你似乎不假思索地放弃了这个建议。

标签: c++ c++11 polymorphism perfect-forwarding


【解决方案1】:

如果您不想按值获取 std::string,有一种方法使用 mixin 类,但它需要更改您的类层次结构:

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 只需写入一次。从那时起,任何源自base_t 的东西都可以从process_mixin 派生出来,您将获得一个完美的转发接口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-22
    • 2021-06-17
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多