C++ 11实现lazy延时加载

2020-12-23  本文已影响0人  FredricZhu

实现原理,
代码摘抄自《深入应用C++11》一书,修复了一个左值构造函数的bug。

  1. 所有的可调用对象,在C++ 11里面都可以转换为std::function类型。
  2. 所有的带参数的函数,都可以使用参数引用捕获的技术转换为 无参数的 lambda表达式。
  3. 使用可变参数模板封装对象构造。
  4. 使用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
上一篇下一篇

猜你喜欢

热点阅读