语法繁重的多重lambda包装器的替代方案-如何避免样板代码
Alternative to syntactically-heavy multiple lambda wrapper - how to avoid boilerplate code?
我发现自己在代码的各个部分用一个更好的接口将多个Lambda封装在一个"代理"对象中:
auto create_proxy()
{
auto f_get_foo = [something]
{
return something_else();
};
auto f_set_bar = [something](auto x)
{
something_else(x);
};
auto f_render = [&window]
{
window.render();
};
return make_nice_proxy( // .
std::move(f_get_foo), // .
std::move(f_set_bar), // .
std::move(f_render));
}
我可以这样使用代理:
nice_proxy.get_foo(); // calls the stored `f_get_foo` lambda
nice_proxy.set_foo(15); // calls the stored `f_set_foo` lambda
nice_proxy.render(); // calls the stored `f_render` lambda
问题是,为这些代理编写和维护代码非常麻烦,语法也很重:
template < // .
typename TFGetFoo, // .
typename TFSetBar, // .
typename TFRender // .
>
class nice_proxy_impl
{
// Hide the lambdas:
private:
TFGetFoo _f_get_foo;
TFSetBar _f_set_bar;
TFRender _f_render;
int _render_count = 0;
public:
template < // .
typename TFwdFGetFoo, // .
typename TFwdFSetBar, // .
typename TFwdFRender // .
>
nice_proxy_impl( // .
TFwdFGetFoo&& f_get_foo, // .
TFwdFSetBar&& f_set_bar, // .
TFwdFRender&& f_render) // .
: _f_get_foo(FWD(f_get_foo)),
_f_set_bar(FWD(f_set_bar)),
_f_render(FWD(f_render))
{
}
// Expose the lambdas:
void set_bar(int x)
{
some_side_effect();
_f_set_bar(x);
}
auto get_foo()
{
return _f_get_foo();
}
void render()
{
std::cout << "rendering...n";
_f_render();
++_render_count;
}
};
template <typename... TFs>
auto make_nice_proxy(TFs&&... fs)
{
return nice_proxy_impl<std::decay_t<TFs>...>(FWD(fs)...);
}
代理类的目的是:
- 对用户隐藏Lambda
- 给用户一个好的(可能更丰富的)界面,通过它他们可以调用"隐藏的"lambdas
我的代码库中有多个代理类,它们都私下存储一些完全转发的可调用对象(并通过public
函数公开它们),并且是使用make_xxx_proxy
函数创建的。
虽然make_xxx_proxy
通常易于实现且不需要太多维护,但每个代理类(如nice_proxy_impl
)都需要每个函数一个模板参数、每个函数一一个字段和一个完美的转发构造函数参数。
对于多个代理类,即使添加或删除单个"封装函数"也会很快变得令人讨厌。CCD_ 5在CCD_ 6中被重复5次(以不同的形式)。
对于这种"模式",有没有更好、语法不那么重的解决方案
我正在寻找一种方法来避免恒定的lambda/函数重复、类型衰减和完美转发,这只是样板。
如果传递的参数不仅是函数,而且是附加字段,那么make_xxx_proxy
函数也将成为维护的地狱。在这种情况下不能使用参数扩展,并且每个函数都必须衰减和转发。
下面是一个类似make_xxx_proxy
的函数的真实例子。代理可能包含额外的数据/方法,这些数据/方法以各种方式使用"封装的lambda"和额外的字段。这是相应的代理类。
不确定我是否理解您的实际要求,但您可以将make_nice_proxy
简化为只返回一个具有公共成员的本地类(感谢C++14)(这样您就可以聚合initialize)。这避免了必须重写大多数内容:
template <class Getter, class Setter, class Render>
auto make_nice_proxy(Getter&& g, Setter&& s, Render&& r)
{
struct Proxy {
std::decay_t<Getter> _f_get_foo;
std::decay_t<Setter> _f_set_bar;
std::decay_t<Render> _f_render;
int _render_count = 0;
void set_bar(int x) {
some_side_effect();
_f_set_bar(x);
}
auto get_foo() {
return _f_get_foo();
}
void render() {
std::cout << "rendering...n";
_f_render();
++_render_count;
}
};
return Proxy{std::forward<Getter>(g), std::forward<Setter>(s), std::forward<Render>(r)};
}
相关文章:
- 以下示例中如何避免代码复制?C++/库达
- 在完美转发函数中公开参数类型,避免代码重复
- 避免在模板专业中避免代码重复
- C++ 避免代码重复运算符重载
- C++ 在向某些继承树类引入附加接口时避免代码重复
- 在避免代码重复和冲突名称的同时,如何实现多个版本的同一算法
- 在本例中,如何避免代码重复
- C++函子使用,避免代码重复
- 避免代码重复
- 在C 类的方法中避免代码重复
- 如果用户在Ruby with Rice中重新定义initialize(),则避免C++代码中的Segfault
- 当唯一的区别是循环控制语句(在循环主体中具有相同的语句)时,避免代码重复
- 模板部分专用化:如何避免代码重复
- 使用 C++11 复制和移动时避免代码重复
- 在这种情况下如何避免代码重复问题
- 在模板专门化中优化循环和避免代码重复
- 在实现迭代器和const_iterator类时避免代码重复的最佳实践
- 如何避免代码重复,避免因const成员和继承而浪费内存
- 如何在本例中避免代码重复
- 通过实现两个不同于const的函数来避免代码重复