c++ - 实现接受回调的方法的 const 和非常量版本

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

我有以下界面:

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

最佳答案

一种选择是引入一个“蹦床”函数,该函数执行从非constconst 的转换:

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

换句话说,不是对函数进行强制转换,而是定义一个对参数进行强制转换的新函数。

关于c++ - 实现接受回调的方法的 const 和非常量版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35305393/

相关文章:

c++ - std::is_base_of() 深度

Python Lambda 实践

C++模板指向成员

c++ - 如何将 unique_ptr 的 vector 声明为类数据成员?

c++ - 直接调用析构函数后 `new (this) MyClass();`是不是未定义行为?

c++ - 可变模板化结构/boost::variant 是如何实现的

c++ - 垂直按位计数(同一位置上的总和)

c++ - 有没有办法轻松处理返回 std::pairs 的函数?

java - 为什么无法加载 lambda 类?

python - 这个 Python 表达式是什么意思?