std::packaged_task

https://www.cnblogs.com/haippy/p/3279565.html

https://en.cppreference.com/w/cpp/thread/packaged_task

std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类似,只不过 std::packaged_task 将其包装的可调用对象的执行结果传递给一个 std::future 对象(该对象通常在另外一个线程中获取 std::packaged_task 任务的执行结果)。

std::packaged_task 对象内部包含了两个最基本元素,一、被包装的任务(stored task),任务(task)是一个可调用的对象,如函数指针、成员函数指针或者函数对象,二、共享状态(shared state),用于保存任务的返回值,可以通过 std::future 对象来达到异步访问共享状态的效果。

可以通过 std::packged_task::get_future 来获取与共享状态相关联的 std::future 对象。在调用该函数之后,两个对象共享相同的共享状态,具体解释如下:

  • std::packaged_task 对象是异步 Provider,它在某一时刻通过调用被包装的任务来设置共享状态的值。
  • std::future 对象是一个异步返回对象,通过它可以获得共享状态的值,当然在必要的时候需要等待共享状态标志变为 ready.
#include <iostream>     // std::cout
#include <utility> // std::move
#include <future> // std::packaged_task, std::future
#include <thread> // std::thread int main ()
{
std::packaged_task<int(int)> foo; // 默认构造函数. // 使用 lambda 表达式初始化一个 packaged_task 对象.
std::packaged_task<int(int)> bar([](int x){return x*;}); foo = std::move(bar); // move-赋值操作,也是 C++11 中的新特性. // 获取与 packaged_task 共享状态相关联的 future 对象.
std::future<int> ret = foo.get_future(); std::thread(std::move(foo), ).detach(); // 产生线程,调用被包装的任务. int value = ret.get(); // 等待任务完成并获取结果.
std::cout << "The double of 10 is " << value << ".\n"; return ;
}
#include <iostream>
#include <cmath>
#include <thread>
#include <future>
#include <functional> // unique function to avoid disambiguating the std::pow overload set
int f(int x, int y) { return std::pow(x,y); } void task_lambda()
{
std::packaged_task<int(int,int)> task([](int a, int b) {
return std::pow(a, b);
});
std::future<int> result = task.get_future(); task(, ); std::cout << "task_lambda:\t" << result.get() << '\n';
} void task_bind()
{
std::packaged_task<int()> task(std::bind(f, , ));
std::future<int> result = task.get_future(); task(); std::cout << "task_bind:\t" << result.get() << '\n';
} void task_thread()
{
std::packaged_task<int(int,int)> task(f);
std::future<int> result = task.get_future(); std::thread task_td(std::move(task), , );
task_td.join(); std::cout << "task_thread:\t" << result.get() << '\n';
} int main()
{
task_lambda();
task_bind();
task_thread();
} /*
输出结果
task_lambda: 512
task_bind: 2048
task_thread: 1024
*/

std::remove_reference

https://en.cppreference.com/w/cpp/types/remove_reference

If the type T is a reference type, provides the member typedef type which is the type referred to by T. Otherwise typeis T.

std::move和std::forward

不错,可以仔细看看: https://www.jianshu.com/p/b90d1091a4ff

https://www.cnblogs.com/boydfd/p/5182743.html

std::function和std::bind

https://www.jianshu.com/p/f191e88dcc80

https://blog.csdn.net/zzhongcy/article/details/88018204

std::function

  • std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
  • 定义格式:std::function<函数类型>。
  • std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
//不同类型可能具有相同的调用形式,如:
// 普通函数
int add(int a, int b){return a+b;} // lambda表达式
auto mod = [](int a, int b){ return a % b;} // 函数对象类
struct divide{
int operator()(int denominator, int divisor){
return denominator/divisor;
}
}; //上述三种可调用对象虽然类型不同,但是共享了一种调用形式:
int(int ,int) //std::function就可以将上述类型保存起来,如下:
std::function<int(int ,int)> a = add;
std::function<int(int ,int)> b = mod ;
std::function<int(int ,int)> c = divide();

std::bind

可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:

  • 将可调用对象和其参数绑定成一个防函数;
  • 只绑定部分参数,减少可调用对象传入的参数。

绑定普通函数:

double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,);
std::cout << fn_half() << '\n'; // /*
bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
_1表示占位符,位于<functional>中,std::placeholders::_1;
*/

绑定成员函数:

/*
bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;
*/
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = ;
};
int main()
{
Foo foo;
auto f = std::bind(&Foo::print_sum, &foo, , std::placeholders::_1);
f(); //
}

std::rec和std::cref

https://blog.csdn.net/lmb1612977696/article/details/81543802

http://www.cnblogs.com/jiayayao/p/6527713.html

C++本身有引用(&),为什么C++11又引入了std::ref?

  主要是考虑函数式编程(如std::bind)在使用时,是对参数直接拷贝,而不是引用。

#include <functional>
#include <iostream> void f(int& n1, int& n2, const int& n3)
{
std::cout << "In function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
++n1; // 增加存储于函数对象的 n1 副本
++n2; // 增加 main() 的 n2
//++n3; // 编译错误
std::cout << "In function end: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
} int main()
{
int n1 = , n2 = , n3 = ;
std::cout << "Before function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
bound_f();
std::cout << "After function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
}

std::result_of

https://zh.cppreference.com/w/cpp/types/result_of

它可以在编译的时候推导出一个函数表达式的返回值类型

#include <type_traits>
#include <iostream> struct S {
double operator()(char, int&);
float operator()(int) { return 1.0;}
}; template<class T>
typename std::result_of<T(int)>::type f(T& t)
{
std::cout << "overload of f for callable T\n";
return t();
} template<class T, class U>
int f(U u)
{
std::cout << "overload of f for non-callable T\n";
return u;
} int main()
{
// 以 char 和 int 参数调用 S 的结果是 double
std::result_of<S(char, int&)>::type d = 3.14; // d 拥有 double 类型
static_assert(std::is_same<decltype(d), double>::value, ""); // 以 int 参数调用 S 的结果是 float
std::result_of<S(int)>::type x = 3.14; // x 拥有 float 类型
static_assert(std::is_same<decltype(x), float>::value, ""); // result_of 能以指向成员函数的指针以如下方式使用
struct C { double Func(char, int&); };
std::result_of<decltype(&C::Func)(C, char, int&)>::type g = 3.14;
static_assert(std::is_same<decltype(g), double>::value, ""); f<C>(); // C++11 中可能编译失败; C++14 中调用不可调用重载
}

C++笔记--std::相关的更多相关文章

  1. MySQL学习笔记-事务相关话题

    事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...

  2. C++11 学习笔记 std::function和bind绑定器

    C++11 学习笔记 std::function和bind绑定器 一.std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法 ...

  3. Linux系列笔记 - vim相关记录

    一.常用到的vim命令 这里只简单记录常用到的命令,后面会有自己记录的命令,但有些可能不常用. 常规模式: gg 跳到文件头 shift+g 跳到文件尾 行数+gg 跳到指定行 如:123gg 跳到1 ...

  4. 工作笔记6-java相关

    1.有时候安装失败或者要装新版本的JDK,可先卸载JDK: a.   首先执行命令查看服务器下的JDK的版本:命令如下:rpm -qa |grep jdk b.   然后执行命令:yum -y rem ...

  5. HTTP笔记01-http相关的基础知识

    这个系列文章是阅读<图解HTTP>后写下的笔记 当我们在浏览器输入url,点击回车后,浏览器显示我们需要的web页面,那么,这个界面是如何产生的? 根据浏览器地址中输入的url,浏览器从相 ...

  6. MVC笔记 Controller相关技术

    一.Controller的责任 MVC的核心就是Controller(控制器),它负责处理浏览器传送过来的所有请求,并决定要将什么内容响应给浏览器.但Controller并不负责决定内容应该如何显示, ...

  7. Linux 路由 学习笔记 之一 相关的数据结构

    http://blog.csdn.net/lickylin/article/details/38326719 从现在开始学习路由相关的代码,在分析代码之前, 我们还是先分析数据结构,把数据结构之间的关 ...

  8. C#图解教程学习笔记——类相关的概念

    一.一些基本概念1. 字段:隶属于类的变量,即类的成员变量.2. 方法:隶属于类的函数,即类的成员函数.3. 实例成员:类的每个实例拥有自己的各个类成员的副本,这些成员称为实例成员. 改变一个实例字段 ...

  9. golang学习笔记 go 相关命令

    go build 命令一些可选项的用途和用法 在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包.当然,如果被依赖的代码包的归档文件(*.a)不存在,或者源码文件有了变化,那么 ...

随机推荐

  1. JsChart组件使用

    JsChart是什么? JSChart能够在网页上生成图标,常用于统计信息,十分好用的一个JS组件. 使用JsChart 一.导入jscharts.js 二.编写jscharts.jsp测试页面 下载 ...

  2. 解读经典《C#高级编程》第七版 Page100-107.继承.Chapter4

    前言 本章节继续讲实现继承. 实现继承 密封类和密封方法 密封类和方法的概念很简单,就是为了不允许类和方法被继承和扩展.不允许扩展一般的原因有: 如果类或者方法被扩展,可能会导致类库执行错误 因为版权 ...

  3. Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)

    通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...

  4. 浅谈_依赖注入 asp.net core

    1.1什么是依赖 我们先看下图 可以简单理解,一个HomeController类使用到了DBContext类,而这种关系是有偶然性,临时性,弱关系的,但是DBContext的变化会影响到HomeCon ...

  5. 修改tomcat的端口号

    一.环境 tomcat7.0.notepad++(这个是一个文本编辑器,用记事本也可以) 二.修改方法 端口        第一步:找到tomcat7的conf目录下的 server.xml这个文件, ...

  6. win10安装ubuntu16.04双系统

    前话:因为感兴趣吧也是专业需要,所以自学了U盘重装系统以及在win10的情况下安装Ubuntu16.04双系统.借此博客,记录下我安装Ubuntu的过程,方便日后回忆. 正因如此,本篇博客会写的十分简 ...

  7. Java多线程编程实战读书笔记(一)

    多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.

  8. HTML和CSS前端教程05-CSS盒模型

    目录 1. CSS盒模型 1.1 元素的尺寸 1.2. 元素内边距 padding 1.3. 元素外边距 margin 1.4. 处理溢出overflow 1.5. 元素的可见性Visibility ...

  9. BGP:所有邻居都启动了BGP,则无须建立首尾逻辑邻居,否则就需要首尾建立逻辑邻居。

    配置说明:都通过loopback 口作为bgp 连接口,并且要配置ebgp多跳,同时配置loopback口的静态路由. 以AR2为例: 第一种场景:所有直接相连的邻居都启动了BGP,则路由可以随意扩散 ...

  10. rxjava切换线程避免重复代码

    .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThrea ...