Recently I was studying about the benefits and uses of std::optional in C++17 (Bartek's Blog) and there I saw a line that said "std::optional can be used for Lazy Loading of Resources" . Upon digging a little bit, I saw that C++ does not have native support for Lazy evaluation. So I just gave it a try and wrote the following code for lazy evaluation in C++.
Lazy.ixx - Visual Studio(Experimental :Modules)
To compile this (VS2019):
cl /experimental:module /EHsc /TP /MD /std:c++latest Lazy.ixx /module:interface /module:output Lazy.pcm /Fo: Lazy.obj /c
#include<optional>
#include<functional>
export module Lazy;
export namespace gstd
{
template<typename T>
class Lazy
{
std::optional<T> m_resource;
std::function<T()>m_ctor_func;
public:
Lazy(std::function<T()>ctor_func)
{
m_ctor_func=ctor_func;
}
std::optional<T> operator ->()
{
//If resource is not initialized(i.e Ctor not invoked/ first time use)
if(!m_resource)
{
m_resource=m_ctor_func();
}
return m_resource;
}
};
}
Now sorry for using modules! (I just love them). To use this class it's pretty simple:
//main.cpp
#include<iostream>
import Lazy;
// A simple class called Resource
class Resource
{
public:
Resource()
{
std::cout<<"Welcome to new C++\n";
}
Resource(int a, int b)
{
std::cout<<"This also works : "<<a<<" "<<b<<"\n";
}
void func()
{
std::cout<<"Resource::func()\n";
}
};
int main()
{
gstd::Lazy<Resource>resx([](){ return Resource(4,5); });
std::cout<<"Before construction\n";
//Some code before using the resource
resx->func();
std::cin.get();
return 0;
}
To compile this:
cl /experimental:module /module:reference Lazy.pcm /std:c++latest /TP /MD /EHsc /c /Fo: main.obj main.cpp
Get the executable by linking those two files:
cl main.obj Lazy.obj
I am pretty much new to programming so please bear me with the silly mistakes. One problem that can be seen at the first glance is this class (Lazy) is not thread-safe. Implementing that would be easy with mutexes. But, other than that, how can I improve my code?
std::optionalif you always return it with the value set? \$\endgroup\$T*, people can't do strange things with it without explicitly callingoperator->. That's what the standard facilities do (and is the intended method). \$\endgroup\$