• c++11实现l延迟调用(惰性求值)


    惰性求值

        惰性求值一般用于函数式编程语言中,在使用延迟求值的时候,表达式不在它被绑定到变量之后就立即求值,而是在后面的某个时候求值。 
        可以利用c++11中的std::function, lambda表达式以及c++11实现的Optional来实现lazy。其中,std::function用来保存传入的函数,不马上执行,而是延迟到后面需要使用值的时候才执行,函数的返回值被放到一个Optional对象中(可以更方便的知道是否求值完毕,使用起来更方便)。通过optional对象可以知道是否已经求值,当发现已经求值的时候直接返回之前计算的结果,起到了缓存的作用。

    c++11实现延迟(惰性)求值【代码均参考网上】

    (1) Optional.hpp

    //Optional.hpp 实现 Optional
    #include<type_traits>
    #include<iostream>
    #include<string>
    #include<map>
    using namespace std;
    template<typename T>
    class Optional
    {
    	using data_t = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
    public:
    	Optional() : m_hasInit(false) {}
    	Optional(const T& v)
    	{
    		Create(v);
    	}
    
    	Optional(T&& v) : m_hasInit(false)
    	{
    		Create(std::move(v));
    	}
    
    	~Optional()
    	{
    		Destroy();
    	}
    
    	Optional(const Optional& other) : m_hasInit(false)
    	{
    		if (other.IsInit())
    			Assign(other);
    	}
    
    	Optional(Optional&& other) : m_hasInit(false)
    	{
    		if (other.IsInit())
    		{
    			Assign(std::move(other));
    			other.Destroy();
    		}
    	}
    
    	Optional& operator=(Optional &&other)
    	{
    		Assign(std::move(other));
    		return *this;
    	}
    
    	Optional& operator=(const Optional &other)
    	{
    		Assign(other);
    		return *this;
    	}
    
    	template<class... Args>
    	void emplace(Args&&... args)
    	{
    		Destroy();
    		Create(std::forward<Args>(args)...);
    	}
    
    	bool IsInit() const { return m_hasInit; }
    
    	explicit operator bool() const {
    		return IsInit();
    
    	}
    
    	T& operator*()
    	{
    		if (IsInit())
    		{
    			return *((T*)(&m_data));
    		}
    
    		throw std::logic_error("is not init");
    	}
    
    	T const& operator*() const
    	{
    		if (IsInit())
    		{
    			return *((T*)(&m_data));
    		}
    
    		throw std::logic_error("is not init");
    	}
    
    	bool operator == (const Optional<T>& rhs) const
    	{
    		return (!bool(*this)) != (!rhs) ? false : (!bool(*this) ? true : (*(*this)) == (*rhs));
    	}
    
    	bool operator < (const Optional<T>& rhs) const
    	{
    		return !rhs ? false : (!bool(*this) ? true : (*(*this) < (*rhs)));
    	}
    
    	bool operator != (const Optional<T>& rhs)
    	{
    		return !(*this == (rhs));
    	}
    private:
    	template<class... Args>
    	void Create(Args&&... args)
    	{
    		new (&m_data) T(std::forward<Args>
    
    			(args)...);
    		m_hasInit = true;
    	}
    
    	void Destroy()
    	{
    		if (m_hasInit)
    		{
    			m_hasInit = false;
    			((T*)(&m_data))->~T();
    		}
    	}
    
    	void Assign(const Optional& other)
    	{
    		if (other.IsInit())
    		{
    			Copy(other.m_data);
    			m_hasInit = true;
    		}
    		else
    		{
    			Destroy();
    		}
    	}
    
    	void Assign(Optional&& other)
    	{
    		if (other.IsInit())
    		{
    			Move(std::move(other.m_data));
    			m_hasInit = true;
    			other.Destroy();
    		}
    		else
    		{
    			Destroy();
    		}
    	}
    
    	void Move(data_t&& val)
    	{
    		Destroy();
    		new (&m_data) T(std::move(*((T*)
    
    			(&val))));
    	}
    
    	void Copy(const data_t& val)
    	{
    		Destroy();
    		new (&m_data) T(*((T*)(&val)));
    	}
    
    private:
    	bool m_hasInit;
    	data_t m_data;
    };
    

     (2) Lazy.cpp

    #include"Optional.hpp"
    #include<memory>
    #include<functional>
    template<typename T>
    struct Lazy{
    	Lazy(){};
    	//保存需要延迟执行的函数
    	template<typename Func, typename ...Args>
    	Lazy(Func& f, Args&&... args){ //给出需要调用的函数和参数,封装起来。等待之后被调用
    		m_func = [&f, &args...]{return f(args...); };
    	}
    	//延迟执行,将结果放到optional中缓存起来,下次不用重新计算可以直接得到结果
    	T& Value(){
    		if (!m_value.IsInit()){
    			m_value = m_func();
    		}
    		return *m_value;
    	}
    
    	bool IsValueCreated()const{
    		return m_value.IsInit();
    	}
    private:
    	std::function<T()> m_func;		//返回值类型为T的无参可调用对象 m_func
    	Optional<T> m_value;	
    };
    
    //定义一个模板函数,返回值类型为 Lazy
    template<class Func, typename... Args>
    Lazy<typename std::result_of<Func(Args...)>::type> lazy(Func&& fun, Args&& ...args){
    	return Lazy<typename std::result_of<Func(Args...)>::type>(std::forward<Func>(fun), std::forward<Args>(args)...);
    }
    
    
    struct BigObject{
    	BigObject(){
    		cout << "lazy load big object" << 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;
    }
    
    
    void TestLazy(){
    
    	//带参数的普通函数
    	int y = 4;
    	auto lazyer1 = lazy(Foo, y);
    	cout << lazyer1.Value() << endl;
    
    	//不带参数的lambda
    	Lazy<int> lazyer2 = lazy([]{return 12; });
    	cout << lazyer2.Value() << endl;
    
    	//带参数的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(){
    	TestLazy();
    	return 0;
    }
    
  • 相关阅读:
    WCF 第十章 异常处理 创建并使用强类型错误
    WCF 第十章 总结
    WCF 第十章 异常处理
    WCF 第十章 异常处理 使用FaultException管理服务异常
    WCF 第十章 异常处理 通信异常细节
    哪本书是对程序员最有影响、每个程序员都该阅读的书?(转自外刊IT评论)
    WCF 第十一章 工作流服务 从WF调用一个WCF服务
    比尔盖茨给大学毕业生的11条人生忠告
    王爽 汇编语言 实验七
    王爽 汇编语言 实验五第5题和第6题
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4811614.html
Copyright © 2020-2023  润新知