C++ functional


类模板std::function是通用多态函数封装器。 std::function的实例能存储、复制及调用任何可调用函数、 lambda表达式、 bind表达式或其他函数对象,还有指向成员函数指针和指向数据成员指针。
若 std::function 不含目标,则称它为空。调用空std::function的目标导致抛出std::bad_function_call异常。

std::function std::bad_function_call

function是一个类模板,模板声明如下。

  • 构造函数支持默认构造(空function,不是一个有效的function)、引用类型、右值引用、拷贝赋值运算符支持的类型也很全。
  • 重载了bool()可以用于判断function是否是有效的
  • 支持交互function
  • 重载了(),支持不定参数
  • 支持获取函数类型信息target_type
template<class> class function; // undefined
template<class R, class... ArgTypes>
class function<R(ArgTypes...)>
  : public unary_function<T1, R>      // iff sizeof...(ArgTypes) == 1 and ArgTypes contains T1
  : public binary_function<T1, T2, R> // iff sizeof...(ArgTypes) == 2 and ArgTypes contains T1 and T2
{
public:
    typedef R result_type;

    // construct/copy/destroy:
    function() noexcept;
    function(nullptr_t) noexcept;
    function(const function&);
    function(function&&) noexcept;
    template<class F> function(F);

    function& operator=(const function&);
    function& operator=(function&&) noexcept;
    function& operator=(nullptr_t) noexcept;
    template<class F> function& operator=(F&&);
    template<class F> function& operator=(reference_wrapper<F>) noexcept;

    ~function();

    // function modifiers:
    void swap(function&) noexcept;

    // function capacity:
    explicit operator bool() const noexcept;

    // function invocation:
    R operator()(ArgTypes...) const;

    // function target access:
    const std::type_info& target_type() const noexcept;
    template <typename T>       T* target() noexcept;
    template <typename T> const T* target() const noexcept;
};
  • 例子
    尽量覆盖大部分功能
#include <functional>
#include <iostream>

struct S {
    void operator ()() { std::cout << "S::()" << std::endl; }
};
void f() { std::cout << "f()" << std::endl; }
void ff() { std::cout << "ff()" << std::endl; }

int main(int argc, char *argv[])
{
    std::function<void()> f1(f);
    std::function<void()> f2(f1);
    f1(); // 输出f()
    f2(); // 输出f()
    f2 = ff;
    f2(); // 输出ff()
    f1.swap(f2);
    f1(); // 输出ff()
    f2(); // 输出f()
    std::cout << f1.target_type().name() << ", " << f2.target_type().name() << std::endl; // 可能输出PFvvE, PFvvE
    std::function<void()> f3 = S();
    f3(); // 输出S::()
    std::function<void()> f4;
    std::cout << (f4 ? "valid" : "invalid") << std::endl;  // 输出invalid
    try { f4(); } catch(std::bad_function_call e) { std::cout << e.what(); /*std::exceptionvalid*/ }
    f4 = f2;
    std::cout << (f4 ? "valid" : "invalid") << std::endl; // 输出valid
    auto f5 = [](){std::cout << "lambda" << std::endl;};
    auto f6 = [](int i){std::cout << "lambda with parameter " << i << std::endl;};
    f5(); // 输出lambda
    f6(100); // 输出lambda with parameter 100
    return 0;
}

std::bind

  • bind是一个函数模块,支持带返回值,它会返回类模板__bind对象,我们可以通过调用__bind中的()调用函数,它会自动填充我们设置的参数。
  • __bind通过tuple存储我们传入的参数,在我们调用()的时候再依次取出
template<class _Fp, class ..._BoundArgs>
inline _LIBCPP_INLINE_VISIBILITY __bind<_Fp, _BoundArgs...> bind(_Fp&& __f, _BoundArgs&&... __bound_args)
{
    typedef __bind<_Fp, _BoundArgs...> type;
    return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...);
}

template<class _Rp, class _Fp, class ..._BoundArgs>
inline _LIBCPP_INLINE_VISIBILITY __bind_r<_Rp, _Fp, _BoundArgs...> bind(_Fp&& __f, _BoundArgs&&... __bound_args)
{
    typedef __bind_r<_Rp, _Fp, _BoundArgs...> type;
    return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...);
}

template<class _Fp, class ..._BoundArgs>
class __bind : public __weak_result_type<typename decay<_Fp>::type>
{
protected:
    typedef typename decay<_Fp>::type _Fd;
    typedef tuple<typename decay<_BoundArgs>::type...> _Td;
private:
    _Fd __f_;
    _Td __bound_args_;

    typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices;
public:
    template <class _Gp, class ..._BA,
              class = typename enable_if<is_constructible<_Fd, _Gp>::value &&
                                  !is_same<typename remove_reference<_Gp>::type, __bind>::value>::type>
      _LIBCPP_INLINE_VISIBILITY
      explicit __bind(_Gp&& __f, _BA&& ...__bound_args)
        : __f_(_VSTD::forward<_Gp>(__f)),
          __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {}

    template <class ..._Args>
        _LIBCPP_INLINE_VISIBILITY
        typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&& ...__args)
        {
            return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
        }

    template <class ..._Args>
        _LIBCPP_INLINE_VISIBILITY
        typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type  operator()(_Args&& ...__args) const
        {
            return _VSTD::__apply_functor(__f_, __bound_args_, __indices(),  tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
        }
};
  • 例子
#include <functional>
#include <iostream>

struct S {
    S(int i) : i(i) {}
    void f1() { std::cout << "[" << i << "] " << "S::f()" << std::endl; }
    void f2(int a1, int& a2) { std::cout << "a1=" << a1 << ", a2=" << a2 << std::endl; a2=100; }
    int i;
};

int main(int argc, char *argv[])
{
    // ctor
    S s(0);
    std::function<void()> f1 = std::bind(&S::f1, &s);
    std::function<void()> f2 = std::bind(&S::f1, std::move(S(1)));
    f1(); // [0] S::f()
    f2(); // [1] S::f()
    int a1 = 5, a2 = 10;
    std::function<void()> f3 = std::bind(&S::f2, &s, a1, std::ref(a2));
    f3(); // a1=5, a2=10
    std::cout << "a1=" << a1 << ", a2=" << a2 << std::endl; // a1=5, a2=100
    return 0;
}

std::ref std::cref std::reference_wrapper

函数模板refcref是生成std::reference_wrapper类型对象的帮助函数,它们用模板实参推导确定结果的模板实参。上面的bind例子有用到。

std::mem_fn

mem_fn是一个函数模板,以下是mem_fn的定义,它的返回值是指向成员指针的包装对象__mem_fn

template<class _Rp, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::* __pm) _NOEXCEPT
{
    return __mem_fn<_Rp _Tp::*>(__pm);
}
  • 例子
#include <functional>
#include <iostream>

struct S {
    S(int i = 0) : i(i) {}
    ~S() = default;
    void f1() { std::cout << "[" << this << "] i = " << i << std::endl; }
    int i;
};

int main(int argc, char *argv[])
{
    S s1(10), s2(100);
    auto f1 = std::mem_fn(&S::f1);
    f1(&s1);f1(&s2);
    return 0;
}
  • 输出
[0x7ffee7f5e138] i = 10
[0x7ffee7f5e130] i = 100
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值