[C++]C++ Simple Lazy class

  • 10646
  • 0
  • C++
  • 2012-01-04

[C++]C++ Simple Lazy class

延遲載入是程式寫作時很重要的一個概念,能讓物件要用在建立,避免不必要的運算。這篇簡單示範一下如何使用VC++ 2010以後的Lambda表示式撰寫C++版本的Lazy類別,透過std::function與template搭配使用,可以將lambda或是Callback Function儲存,當物件要建立時再透過剛儲存的初始動作執行。

#include <functional>

template<class T>
class Lazy
{
#pragma region Var
private:
	std::function<T (void)>		_func;
	T							_result;
	bool						_bIsValueCreated;
#pragma endregion


	
#pragma region Private Property
private:
	__declspec(property(get=Get_func,put=Set_func))
		std::function<T (void)> m_func;
#pragma endregion

	
	
#pragma region Public Property
public:
	__declspec(property(get=Get_result))
		T m_result;

	__declspec(property(get=Get_bIsValueCreated,put=Set_bIsValueCreated))
		bool m_bIsValueCreated;
#pragma endregion
	
	

#pragma region Constructor & DeConstructor
public:		
	Lazy(std::function<T (void)> func)
	{
		Reset();
		m_func = func;
	}

	~Lazy(void)
	{
		Reset();
	}
#pragma endregion


	
#pragma region Property Process Method
private:
	inline std::function<T (void)> Get_func()
	{
		return _func;
	}

	inline void Set_func(std::function<T (void)> value)
	{
		_func = value;
	}

	inline void Set_bIsValueCreated(bool value)
	{
		_bIsValueCreated = value;
	}

public:
	inline T Get_result()
	{
		if(!m_bIsValueCreated)
		{
			Init();
		}
		return _result;
	}

	inline bool Get_bIsValueCreated()
	{
		return _result;
	}
#pragma endregion


#pragma region Protected Method
protected:
	void Reset()
	{
		_func				=	NULL;
		_result				=	NULL;
		_bIsValueCreated	=	false;
	}
#pragma endregion


#pragma region Public Method
public:
	void Init()
	{
		if(m_bIsValueCreated)
			return;
		_result = m_func();
		m_bIsValueCreated=true;
	}

	void ClearValue()
	{
		std::function<T (void)> func = m_func;
		Reset();
		m_func = func;
	}
#pragma endregion
};

 

使用上像是下面這般,這邊示範的是將一個簡單的Lambda設給Lazy物件,Lambda裡面會做初始動作,這邊我以簡單的運算示意,透過Lazy.m_bIsValueCreated可以判斷是否已初始完成,而透過Lazy.m_result則是會做初始動作並將初始完的值回傳。

int _tmain(int argc, _TCHAR* argv[])
{
	auto lazyObj = Lazy<int>([]()
	{
		return 1 + 2;
	});
	printf("IsValueCreated: %d\n",lazyObj.m_bIsValueCreated);
	printf("Value: %d\n",lazyObj.m_result);
	printf("IsValueCreated: %d\n",lazyObj.m_bIsValueCreated);
	return 0;
}

 

運行結果如下,可以看到一開始是未初始化的,當使用了Lazy.m_result才會做初始的動作,也才可以取到我們想要的值。

image