实现原理,
代码摘抄自《深入应用C++11》一书,修复了一个左值构造函数的bug。
- 所有的可调用对象,在C++ 11里面都可以转换为std::function类型。
- 所有的带参数的函数,都可以使用参数引用捕获的技术转换为 无参数的 lambda表达式。
- 使用可变参数模板封装对象构造。
- 使用Value方法实现延时加载。
lazy.hpp
#ifndef _LAZY_HPP_
#define _LAZY_HPP_
#include <boost/optional.hpp>
#include <functional>
using boost::optional;
template <typename T>
struct Lazy {
Lazy() {}
template <typename Func, typename ... Args>
Lazy(Func&& f, Args && ... args) {
m_func = [&f, &args...] {return f(args...);};
}
T& Value() {
if(!m_value.is_initialized()) {
m_value = m_func();
}
return *m_value;
}
bool IsValueCreated() const {
return m_value.is_initialized();
}
private:
std::function<T()> m_func;
optional<T> m_value;
};
// 提供一个可以直接调用的lazy函数,生成一个Lazy对象
template <typename T>
using RetLazy = Lazy<typename std::result_of<T>::type>;
template <typename Func, typename ... Args>
RetLazy<Func(Args...)> lazy(Func && func, Args&& ... args) {
return RetLazy<Func(Args...)>(std::forward<Func>(func), std::forward<Args>(args)...);
}
#endif
main.cpp
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
#include "lazy.hpp"
#include <cstdlib>
// 用于测试延时加载的大对象
struct BigObject {
BigObject() {
cout << "Lazy load big object..." << endl;
}
};
struct MyStruct {
MyStruct() {
m_obj = lazy([]{return std::make_shared<BigObject>();});
}
// 调用.Value函数真正调用lambda函数,加载大对象
void Load() {
m_obj.Value();
}
private:
Lazy<std::shared_ptr<BigObject> > m_obj;
};
int Foo(int x) {
return 2 * x;
}
void testLazy() {
// 普通函数延时加载
int y = 4;
auto lazyer1 = lazy(Foo, y);
cout << lazyer1.Value() << endl;
// 不带参数的lambda
auto lazyer2 = lazy([] {return 12;});
cout << lazyer2.Value() << endl;
// 带参数的std::function调用
std::function<int(int)> f = [](int x) {return x+3; };
auto lazyer3 = lazy(f, 3);
cout << lazyer3.Value() << endl;
// 大对象延时加载
MyStruct t;
t.Load();
}
int main(void) {
testLazy();
cout << "请按任意键继续..." << endl;
getchar();
return 0;
}
Makefile文件,
因为使用了boost准标准库中的optional类,所以需要预先安装和编译boost库。
TAR=main
WORKSPACE_DIR=.
CC:=g++
HEADER_PATH = -ID:/software/boost_1_74_0
LIB_PATH = -LD:/software/boost_1_74_0/stage/lib
.PHONY: build clear all
build:
$(CC) -std=c++11 $(WORKSPACE_DIR)/lazy.hpp $(WORKSPACE_DIR)/main.cpp -g -o $(TAR) $(HEADER_PATH) $(LIB_PATH)
all: clear build
clear:
rm -rf $(TAR)
程序输出如下,
图片.png
网友评论