У меня есть следующий интерфейс:Реализовать сопзЬ и неконстантную версии методов, берущих обратного вызова
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()
не является приятным. Мейерс советует консистенцию (см. 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 */);
}
Однако именно это недостающая часть, кажется, невозможно. Я могу получить указатель на функцию cb
с использованием std::function::target()
, а затем попытаться применить его к другому типу. Но это невозможно, так как target()
не работает для лямбда, они не могут быть преобразованы в указатели функций (только если у них есть пустой захват).
Поэтому я не могу придумать решение прямо сейчас. Есть ли у кого-нибудь идеи? Может быть, весь подход испорчен уже: D