我发现自己将多个lambdas封装在"代理"在我的代码的各个部分中具有更好界面的对象:
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)...);
}
代理类的目的是:
我的代码库中有多个代理类,它们都私下存储一些完美转发的可调用对象(并通过public
函数公开它们),并使用{{1}创建}} 功能。
虽然make_xxx_proxy
通常易于实现且不需要太多维护,但每个代理类(如make_xxx_proxy
)每个函数需要一个模板参数,每个函数需要一个字段和一个完美转发构造函数参数。
使用多个代理类,甚至可以添加或删除单个&#34;封装的函数&#34;变得很烦人。 nice_proxy_impl
在get_foo
(以不同的形式)中重复nice_proxy_impl
次。
对于这种&#34;模式&#34;是否有更好的,语法更重的解决方案?
我正在寻找一种避免常数lambda /函数重复的方法,键入衰减和完美转发,这只是样板。
如果传递的参数不仅是函数,而且还有附加字段,那么 make_xxx_proxy
函数也会变得难以维护。在这种情况下不能使用参数扩展,并且每个函数都必须被衰减和转发。
此处make_xxx_proxy
类a real example的the corresponding proxy class功能。代理可能包含其他数据/方法,使用&#34;封装的lambdas&#34;以及各种方式的其他字段。这是css-tricks.com。
答案 0 :(得分:1)
我不确定我理解你的实际问题,但是你可以减少make_nice_proxy
只返回一个本地成员(感谢C ++ 14)与公共成员(所以你可以聚合初始化)。这避免了重写大多数东西:
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)};
}