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;
}

 

原文链接: https://www.cnblogs.com/gtarcoder/p/4811614.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

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

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/221917

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午11:29
下一篇 2023年2月13日 上午11:29

相关推荐