实现接受回调的方法的 const 和非常量版本
Implement const and non-const version of methods taking a callback
我有以下界面:
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 (cf. 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
一种选择是引入一个 "trampoline" 函数,该函数执行从非 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);
}
换句话说,不是对函数进行强制转换,而是定义一个对参数执行强制转换的新函数.
我有以下界面:
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 (cf. 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
一种选择是引入一个 "trampoline" 函数,该函数执行从非 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);
}
换句话说,不是对函数进行强制转换,而是定义一个对参数执行强制转换的新函数.