我最近在网上找到了这个漂亮的片段 - 它允许你绑定而不必传递明确的占位符:
template <typename ReturnType, typename... Args>
std::function<ReturnType(Args...)>
easy_bind(ReturnType(*MemPtr)(Args...))
{
return [=]( Args... args ) -> ReturnType { return (*MemPtr)( args... ); };
}
这个版本很好用,没有args:
auto f1 = easy_bind( (std::string(*)(A&,A&))&Worker::MyFn );
后来调用:
std::string s = f1( *p_a1, *p_a2 );
问题
是否可以修改代码以使用最多n个args,用占位符填充2-n(在本例中)?例如,这个应该有一个占位符:
auto f2 = easy_bind( (std::string(*)(A&,A&))&Worker::MyFn, *p_a1 );
后来调用:
std::string s = f2( *p_a2 );
加成
最终,有这样的东西很好(它不会插入任何占位符,因为它会耗尽最后一个占位符),但我不认为它对这个实现是可行的(不能模式匹配签名,我想):
auto f3 = easy_bind( f2, *p_a2 );
后来调用:
std::string s = f3();
最重要的是,拥有一个我不需要放在占位符中的bind版本会很不错 - 它在通用TMP代码中非常有用。
答案 0 :(得分:13)
使用indices trick和the ability to tell std::bind
about your own placeholder types,这就是我想出的:
#include <functional>
#include <type_traits>
#include <utility>
template<int I> struct placeholder{};
namespace std{
template<int I>
struct is_placeholder< ::placeholder<I>> : std::integral_constant<int, I>{};
} // std::
namespace detail{
template<std::size_t... Is, class F, class... Args>
auto easy_bind(indices<Is...>, F const& f, Args&&... args)
-> decltype(std::bind(f, std::forward<Args>(args)..., placeholder<Is + 1>{}...))
{
return std::bind(f, std::forward<Args>(args)..., placeholder<Is + 1>{}...);
}
} // detail::
template<class R, class... FArgs, class... Args>
auto easy_bind(std::function<R(FArgs...)> const& f, Args&&... args)
-> decltype(detail::easy_bind(build_indices<sizeof...(FArgs) - sizeof...(Args)>{}, f, std::forward<Args>(args)...))
{
return detail::easy_bind(build_indices<sizeof...(FArgs) - sizeof...(Args)>{}, f, std::forward<Args>(args)...);
}
请注意,我要求easy_bind
的函数参数为std::function
类型,或者可以转换为它,以便我有明确的签名。
答案 1 :(得分:0)
这让我很烦恼,因为当我不知道当时的论点时,我必须绑定一个函数。 (此处显示的工厂How to implement serialization in C++)
例如(假设TSubClass :: create是静态的)
template<typename TFactoryClass, typename TArgs...>
class Factory
{
public:
template<typename TSubClass>
void register(int id)
{
_map.insert(std::make_pair(id, std::bind(&TClass::create, /*how to give TArgs as placeholders??*/)));
}
}
相反,我能够用lambda表达式替换std :: bind,而不必使用所有这些辅助类!
template<typename TFactoryClass, typename TArgs...>
class Factory
{
public:
template<typename TSubClass>
void register(int id)
{
_map.insert(std::make_pair(id, [](TArgs... args) { TSubClass::create(args...); }));
}
}
作为奖励,你也可以&#34;绑定&#34;使用这种机制的构造函数