通过惰性求值类的实现综合采用了可变模板参数、lambda、type_traits、optional进行实现

该类功能是:当初始化某个对象时,该对象引用了一个大对象,这个对象的创建需要较长的时间,同时有大量的堆内存分配,这样可以会使得整体的初始化变的很慢,尤其是UI应用时会导致用户体验差,其实很多时候并不用马上就获取大数据,只是在需要的时候获取即可,这种场景就很适合延迟加载。

目前C++中还没有类似的Lazy<T>惰性求值类,实现思路比较简单,借助lamda表达式,将函数封装到lamda表达式中,而不是马上求值,是在需要的时候再调用lamda表达式去求值。C++11中的lamda表达式和function正好用来做这样的事。

#ifndef _LAZY_HPP_
#define _LAZY_HPP_#include <boost/optional.hpp>
template<typename T>
struct Lazy
{Lazy(){} // 默认构造函数// 保存需要延迟执行的函数template <typename Func, typename... Args>Lazy(Func& f, Args && ... args){// 使用lamda表达式和function进行绑定,只是绑定先不执行// m_func = [&f, &args...]{return f(args...); }; //这种方式也行m_func = std::bind(f, std::forward<Args>(args)...);}// 延迟执行,将结果放到optionl中缓存起来,下次不用重新计算可以直接返回结果// 此时的T就是返回类型的参数T& Value(){// 这里才是开始调用的地方,只要调用一次即可,不会重复调用// cout << " m_value.is_initialized() = " << m_value.is_initialized() << endl;if (!m_value.is_initialized()){cout << " m_value = m_func() " << endl;m_value = m_func();}return *m_value;}bool IsValueCreated() const{return m_value.is_initialized();}private:std::function<T()> m_func;boost::optional<T> m_value;//这里使用option类,该类主要是判断对象是否初始化,例如只有m_value初始化后,才有// 效果,否则无效,他实现了未初始化的概念,m_value.value进行获取值
};// 创建一个模板函数
template<class Func, typename... Args> // 可变模板参数,
Lazy<typename std::result_of<Func(Args...)>::type> // 通过std::result_of获取返回结果类型即对应是function
lazy(Func && fun, Args && ... args) //右转引用
{return Lazy<typename std::result_of<Func(Args...)>::type>(std::forward<Func>(fun), std::forward<Args>(args)...); //std::result_of结果类型推到 std::forward完美转发
}#endif

测试代码

#include "Lazy.hpp"
#include<string>
#include <iostream>
#include <memory>using namespace std;struct BigObject
{BigObject(){std::cout << "lazy load big object" << std::endl;}
};struct MyStruct
{MyStruct(){m_obj = lazy([]{return std::make_shared<BigObject>(); });}void Load(){m_obj.Value();}Lazy<std::shared_ptr<BigObject>> m_obj;
};int Foo(int x)
{return x * 2;
}int Foo1(int& x, float& y, std::string& z)
{cout << "x = " << x << endl;cout << "y = " << y << endl;cout << "z = " << z << endl;return x * 2;
}void TestLazy()
{//带参数的普通函数int x = 4;float y = 3.1;string str = "hello";auto lazyer1 = lazy(Foo, x);std::cout << lazyer1.Value() << std::endl;// 增加可变参数模板的功能,也就是说我只写一个lazy,该lazy的返回值和参数都是可变的,// 因此在使用该函数模板时就不用考虑太多,这里auto lazyer11 = lazy(Foo1,x,y,str);// 这里的函数是Fool  对应的参数是int float string// 这里的lazyer11是惰性的并不会立刻执行,真正的执行是需要调用lazyer11.Value()// 这里就实现了惰性的需求,这里先绑定,后面在合适的地方执行即可std::cout << lazyer11.Value() << std::endl;std::cout << lazyer11.Value() << std::endl;//不带参数的lamdaLazy<int> lazyer2 = lazy([]{return 12; });std::cout << lazyer2.Value() << std::endl;//带参数的fucntionstd::function < int(int) > f = [](int x){return x + 3; };auto lazyer3 = lazy(f, 3);std::cout << lazyer3.Value() << std::endl;//延迟加载大对象sMyStruct t;t.Load();
}

c++11新特性的使用---可变模板参数、lambda、type_traits、optional综合使用相关推荐

  1. c++11新特性的使用---可变模板参数、type_traits、function综合使用

    DLL帮助类 c++中手动调用dll是比较繁琐的,调用过程是:加载dll后还要定义一个对应的函数指针类型,接着调用GetProAddress获取函数地址,在转成函数指针,最后调用该函数如下例子: #i ...

  2. C++11新特性之泛型编程与模板

    模板 泛型编程 函数模板 普通函数模板 成员函数模板 函数模板重载 模板函数的特化 类模板 类模板中的成员函数模板 类模板的特化与偏特化 类模板成员特化 模板 Template所代表的泛型编程是C++ ...

  3. 【初阶与进阶C++详解】第二十二篇:C++11新特性(列表初始化+变量类型推到+右值引用+新增默认成员函数+可变模板参数+lambda表达式+包装器function_bind)

  4. C++11新特性之 可变参数模板

    C++ 11的可变模版参数是其新增的最强大的特性之一.通过对参数进行了泛化,可以表示从0到任意个数.任意类型的参数.我们知道对于一个模板类来说,通常只能含固定数量的模版参数,可变模版参数无疑是一个巨大 ...

  5. C++11新特性选讲 语言部分 侯捷

    C++11新特性选讲 语言部分 侯捷 本课程分为两个部分:语言的部分和标准库的部分.只谈新特性,并且是选讲. 本文为语言部分笔记. 语言 Variadic Templates move semanti ...

  6. C++11新特性(原封不动转载待查)

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  7. C++11新特性总结

    目录 一. 统一的列表初始化 {}  适用于各种STL容器 二. 类型推导 auto 和 decltype的出现 三. 右值引用移动语义  (特别重要的新特性) 四.  万能引用  +  完美转发 五 ...

  8. 深入浅出之C++11新特性

    1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...

  9. 《深入理解C++11:C++ 11新特性解析与应用》——导读

    前 言 为什么要写这本书 相比其他语言的频繁更新,C++语言标准已经有十多年没有真正更新过了.而上一次标准制定,正是面向对象概念开始盛行的时候.较之基于过程的编程语言,基于面向对象.泛型编程等概念的C ...

最新文章

  1. HDU 4888 Redraw Beautiful Drawings(网络流求矩阵的解)
  2. c++画多边形_水彩画,这么美!怎么画出来的?
  3. @cacheable 是否缓存成功_DNS缓存中毒攻击
  4. 运用 autoconf 和 automake 自动生成 Makefile 实例讲解
  5. 分类信息网站源码_分类信息网站如何增加搜索引收录
  6. c语言程序怎么打分数,用C语言编程平均分数
  7. 世界上速度最慢的10种动物,做什么都慢半拍
  8. fiddler 抓取 安卓模拟器 https包
  9. fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64
  10. 减少文件间的编译依赖
  11. java特征提取_特征提取
  12. Java开发就业前景,2017java开发就业前景分析
  13. java 时钟_Java的指针时钟
  14. 6,Java毕向东百度云盘
  15. (附源码)springboot家庭财务分析系统 毕业设计641323
  16. linux shell 字符串长度
  17. 微机原理与接口技术复习笔记(1)——微型计算机概述
  18. windows server 2012 r2 及 server 2019的sxs文件
  19. ONVIF 事件--能力集
  20. 【Python学习随笔】依赖倒置原则 + 简单工厂模式

热门文章

  1. SQL高手篇:精典SQL FAQ收藏
  2. Metropolis Light Transport学习与实现
  3. java处理表单变量_jsp处理表单及JS和JAVA变量互传
  4. 常见的数据分析思维方式有哪些
  5. 大数据分析哪些错误需避免
  6. 大数据分析在医疗行业的作用
  7. oracle 1亿条数据,如何在十分钟内插入1亿条记录到Oracle数据库?
  8. 计算机专业评定职称论文,《计算机职称论文.doc
  9. gis python趋势变化代码_GIS技术发展趋势——2018年回顾与2019年展望
  10. AcWing 848. 有向图的拓扑序列(拓扑排序模板)