【问题标题】:Implement const and non-const version of methods taking a callback实现带有回调的 const 和非 const 版本的方法
【发布时间】:2016-02-10 01:34:14
【问题描述】:

我有如下界面:

struct A {};

struct B
{
    using Cb = std::function<void(A& a)>;
    using ConstCb = std::function<void(const A& a)>;

    virtual void visit(ConstCb cb) const = 0;
    virtual void visit(Cb cb) = 0;
};

B::visit() 应枚举其自身所有类型为A 的成员。

现在,由于 B::visit() 在派生类时可能会变得复杂,所以复制 visit() 的实现并不好。 Meyers 建议 const-casting(参见here)。

所以一种方法是:

struct B
{
    using Cb = std::function<void(A& a)>;
    using ConstCb = std::function<void(const A& a)>;

    void visit(Cb cb);
    void visit(ConstCb cb) const;

protected:
    virtual void doVisit(ConstCb) const = 0;
};

void B::f(ConstCb cb) const
{
    doVisit(cb);
}

void B::f(Cb cb)
{
    static_cast<const B*>(this)->f(/* somehow cast cb to ConstCb */);
}

然而,这块缺失的部分似乎是不可能的。我可以使用std::function::target() 获得cb 的函数指针,然后尝试将其转换为其他类型。但这是不可能的,因为target() 不适用于 lambda,它们无法转换为函数指针(仅当它们有一个空捕获时)。

所以我现在想不出解决办法。有人有什么想法吗?也许整个方法已经存在缺陷:D

【问题讨论】:

    标签: c++ c++11 lambda const-cast


    【解决方案1】:

    一种选择是引入“蹦床”功能,将非const 转换为const

    void B::f(Cb cb)
    {
        ConstCb trampoline = [&cb] (const A& arg) {
            cb(const_cast<A&>(arg));
        };
        static_cast<const B*>(this)->f(trampoline);
    }
    

    换句话说,与其对函数进行强制转换,只需定义一个对参数进行强制转换的新函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-23
      • 2012-01-09
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多