C++的杂七杂八:如何实现一个简单的bind

本文介绍了如何在C++11中使用变参模板和模板元编程技术实现一个简单的bind功能。C++11的std::bind提供了方便的闭包创建能力,但作者在C++98/03时代通过自定义bind实现类似功能时遇到了挑战。文章讨论了仿函数fr的设计,包括其作为类模板的参数推导和移动构造函数的问题,并预告了将在operator()的实现中解决的关键问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文的草稿我是在2014年5月11号开始打的,可是拖拖拉拉直到现在才真正动笔写,自己对自己也是醉了。。
之所以写bind而不是什么其他的东西,是因为bind在各种C++的utility里面可以说是最能体现出“利用语言本身来拓展语言功能”这一特征的了。

在C++98/03的时代,人们为了让C++具有把函数和参数打包成闭包(closure)这一能力而发明了bind,从而使C++不仅可以存储算法执行的结果,还可以打包算法和算法的传入参数,存储算法执行的动作,直到调用这个闭包的时候才释放出参数并参与算法计算。有了这个东西之后,再配合可以存储任何可调用体的function对象,不少面向对象里麻烦的调用关系可以被简化到不像话的地步(具体可参看此文:以boost::function和boost:bind取代虚函数)。

在C++98/03下实现一个好用的bind是痛苦的。看看Boost.Bind,还有我自己,为了实现一个完善的bind折腾遍了C++的奇巧淫技……这是很划不来的,平时学习或兴趣玩一玩还可以,真在项目工程里这样做了,如何维护会是一个很头痛的事情。

在C++11里事情变得很不一样了。首先stl里就已经给我们提供了好用的std::bind,然后再就是语言本身的进化,让“写一个bind”之类的事情变得无比简单。于是我去年曾花了点时间,用C++11写了下面这个200多行的“simple bind”,用来让自己被C++98/03腌入味的思维习惯向C++11转换一下:

#include <type_traits>
#include <tuple>
#include <utility>
 
namespace simple {
 
/*
    Placeholder
*/
 
template <int N>
struct placeholder {};
 
const placeholder<1> _1; const placeholder<6>  _6;  const placeholder<11> _11; const placeholder<16> _16;
const placeholder<2> _2; const placeholder<7>  _7;  const placeholder<12> _12; const placeholder<17> _17;
const placeholder<3> _3; const placeholder<8>  _8;  const placeholder<13> _13; const placeholder<18> _18;
const placeholder<4> _4; const placeholder<9>  _9;  const placeholder<14> _14; const placeholder<19> _19;
const placeholder<5> _5; const placeholder<10> _10; const placeholder<15> _15; const placeholder<20> _20;
 
/*
    Sequence & Generater
*/
 
template <int... N>
struct seq { typedef seq<N..., sizeof...(N)> next_type; };
 
template <typename... P>
struct gen;
 
template <>
struct gen<>
{
    typedef seq<> seq_type;
};
 
template <typename P1, typename... P>
struct gen<P1, P...>
{
    typedef typename gen<P...>::seq_type::next_type seq_type;
};
 
/*
    Merge the type of tuple
*/
 
template <typename T, typename TupleT>
struct tuple_insert;
 
template <typename T, typename... TypesT>
struct tuple_insert<T, std::tuple<TypesT...>>
{
    typedef std::tuple<T, TypesT...> type;
};
 
template <class TupleT, typename... BindT>
struct merge;
 
template <typename... ParsT>
struct merge<std::tuple<ParsT...>>
{
    typedef std::tuple<> type;
};
 
template <typename... ParsT, typename B1, typename... BindT>
struct merge<std::tuple<ParsT...>, B1, BindT...>
{
    typedef std::tuple<ParsT...> tp_t;
    typedef typename tuple_insert<
            B1, 
            typename merge<tp_t, BindT...>::type
    >::type type;
};
 
template <typename... ParsT, int N, typename... BindT>
struct merge<std::tuple<ParsT...>, const placeholder<N>&, BindT...>
{
    typedef std::tuple<ParsT...> tp_t;
    typedef typename tuple_insert<
            typename std::tuple_element<N - 1, tp_t>::type,
            typename merge<tp_t, BindT...>::type
    >::type type;
};
 
/*
    Select the value of tuple
*/
 
template <typename T, class TupleT>
inline auto select(TupleT& /*tp*/, T&& val) -> T&&
{
    return std::forward<T>(val);
}
 
template <int N, class TupleT>
inline auto select(TupleT& tp, placeholder<N>) -> decltype(std::get<N - 1>(tp))
{
    return std::get<N - 1>(tp);
}
 
/*
    Return type traits
*/
 
template <typename F>
struct return_traits : return_traits<decltype(&F::operator())> {};
 
template <typename T>
struct return_traits<T*> : return_traits<T> {};
 
// check function
 
template <typename R, typename... P>
struct return_traits<R(*)(P...)> { typedef R type; };
 
// check member function
 
#define RESULT_TRAITS__(...) \
    template <typename R, typename C, typename... P> \
    struct return_traits<R(C::*)(P...) __VA_ARGS__> { typedef R type; };
 
RESULT_TRAITS__()
RESULT_TRAITS__(const)
RESULT_TRAITS__(volatile)
RESULT_TRAITS__(const volatile)
 
#undef RESULT_TRAITS__
 
/*
    Type detect
*/
 
template <typename T>
struct is_pointer_noref
    : std::is_pointer<typename std::remove_reference<T>::type>
{};
 
template <typename T>
struct is_memfunc_noref
    : std::is_member_function_pointer<typename std::remove_reference<T>::type>
{};
 
template <typename T>
struct is_wrapper
    : std::false_type
{};
 
template <typename T>
struct is_wrapper<std::reference_wrapper<T>>
    : std::true_type
{};
 
template <typename T>
struct is_wrapper_noref
    : is_wrapper<typename std::remove_reference<typename std::remove_cv<T>::type>::type>
{};
 
/*
    The invoker for call a callable
*/
 
template <typename R, typename F, typename... P>
inline typename std::enable_if<is_pointer_noref<F>::value,
R>::type invoke(F&& f, P&&... args)
{
    return (*std::forward<F>(f))(std::forward<P>(args)...);
}
 
template <typename R, typename F, typename P1, typename... P>
inline typename std::enable_if<is_memfunc_noref<F>::value &&
                               is_pointer_noref<P1>::value,
R>::type invoke(F&& f, P1&& this_ptr, P&&... args)
{
    return (std::forward<P1>(this_ptr)->*std::forward<F>(f))(std::forward<P>(args)...);
}
 
template <typename R, typename F, typename P1, typename... P>
inline typename std::enable_if<is_memfunc_noref<F>::value &&
                              !is_pointer_noref<P1>::value && !is_wrapper_noref<P1>::value,
R>::type invoke(F&& f, P1&& this_obj, P&&... args)
{
    return (std::forward<P1>(this_obj).*std::forward<F>(f))(std::forward<P>(args)...);
}
 
template <typenam
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值