我是靠谱客的博主 坦率信封,最近开发中收集的这篇文章主要介绍std::bind,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

std::bind

定义于头文件 <functional>

template <class F, class... Args>							(since C++11)
/*unspecified*/ bind(F&& f, Args&&... args);				(until C++20)
template < class F, class... Args>						(1)
constexpr /*unspecified*/ bind( F&&f, Args&&... args ); 	(since C++20)

template < class R, class F, class... Args>					(since C++11)
/*unspecified*/ bind( F&&f, Args&&... args);				(until C++20)
template< class R, class F, class... Args >				(2)
constexpr /*unspecified*/ bind( F&& f, Args&&... args );	(since C++20)

函数模板 bind 为f生成一个转发调用包装器。调用这个包装器等价于使用它的一些绑定到args的参数调用f。

Parameters

f - Callable对象(函数对象,函数指针,函数引用,成员函数指针,数据成员指针),将被绑定一些参数
args - 要绑定的参数列表,未绑定的参数用命名空间std::placeholder中的placeholders _1, _2, _3…替换

Return value

未指定类型T的函数对象,对它而言std::is_bind_expression::value == true,有以下成员:

std::bind return type

Member objects

std::bind的返回类型有一个类型为std::decay<F>::type的成员对象,它由 std::forward<F>(f)构造而来。每个arg…有一个对象,类型为 std::decay<Arg_i>::type,类似的由 std::forward<Arg_i>(arg_i) 构造而来。

Constructors

如果其所有成员(上述指定)都是CopyConstructible的,则 std::bind 的返回类型是 CopyConstructible 的,否则返回类型是 MoveConstructible

Member function operator()

给予一个从前述bind的调用中获得的g对象,当它在一个函数表达式g(u1, u2, ...uM)中被调用时,一个存储对象的调用发生,看上去像是 std::invoke<fd, std::forward<V1>(v1, std::forward<V2>(v2), ..., std::forward<VN>(vN))>,其中fd是类型为std::decay_t<F>的值,绑定参数 v1,v2,…,vN 如下述定义:

如果调用*g()中提供的一些参数不匹配任何存储在g()*中的 placehorder,未使用的参数被求值,被丢弃。

如果g是 volatile-qualified (i.e. cv-限定符 volatile 或 const volatile),行为是未定义的。

Notes

正如在 Callable 中描述的,当调用非静态成员函数指针,或非静态数据成员指针,第一个参数必须是指向可访问成员的对象的引用或指针,(包括,可能的,智能指针例如 std::shared_ptr 和 std::unique_ptr)。
bind的参数被拷贝或移动,永远不要使用引用传递,除非使用 std::ref 或 std::cref 进行封装。
在相同的bind表达式中(例如,multiple _1’s) 复制 placeholders 是允许的,但是仅当对应的实参(u1)是左值或不可移动的右值时,结果才是明确定义的。

Example

#include <random>
#include <iostream>
#include <memory>
#include <functional>
 
void f(int n1, int n2, int n3, const int& n4, int n5)
{
    std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << 'n';
}
 
int g(int n1)
{
    return n1;
}
 
struct Foo {
    void print_sum(int n1, int n2)
    {
        std::cout << n1+n2 << 'n';
    }
    int data = 10;
};
 
int main()
{
    using namespace std::placeholders;  // for _1, _2, _3...
 
    std::cout << "demonstrates argument reordering and pass-by-reference:n";
    int n = 7;
    // (_1 and _2 are from std::placeholders, and represent future
    // arguments that will be passed to f1)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused
                    // makes a call to f(2, 42, 1, n, 7)
 
    std::cout << "achieving the same effect using a lambda:n";
    auto lambda = [ncref=std::cref(n), n=n](auto a, auto b, auto /*unused*/) {
        f(b, 42, a, ncref, n);
    };
    lambda(1, 2, 1001); // same as a call to f1(1, 2, 1001)
 
    std::cout << "nested bind subexpressions share the placeholders:n";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5);
 
    std::cout << "common use case: binding a RNG with a distribution:n";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // a copy of e is stored in rnd
    for(int n=0; n<10; ++n)
        std::cout << rnd() << ' ';
    std::cout << 'n';
 
    std::cout << "bind to a pointer to member function:n";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
 
    std::cout << "bind to a pointer to data member:n";
    auto f4 = std::bind(&Foo::data, _1);
    std::cout << f4(foo) << 'n';
 
    std::cout << "use smart pointers to call members of the referenced objects:n";
    std::cout << f4(std::make_shared<Foo>(foo)) << ' '
              << f4(std::make_unique<Foo>(foo)) << 'n';
}

最后

以上就是坦率信封为你收集整理的std::bind的全部内容,希望文章能够帮你解决std::bind所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部