function
是一个类模板,模板声明如下。
bool()
可以用于判断function是否是有效的()
,支持不定参数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
#include
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;
}
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
#include
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;
}
函数模板ref
与cref
是生成std::reference_wrapper
类型对象的帮助函数,它们用模板实参推导确定结果的模板实参。上面的bind例子有用到。
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
#include
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