Lazy Resource Loading class in C++ 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&lt;optional&gt;
#include&lt;functional&gt;
export module Lazy;

export namespace gstd
{
template&lt;typename T&gt;
class Lazy
{
   std::optional&lt;T&gt; m_resource;
   std::function&lt;T()&gt;m_ctor_func;
public:
   Lazy(std::function&lt;T()&gt;ctor_func)
   {
       m_ctor_func=ctor_func; 
   }
   std::optional&lt;T&gt; operator -&gt;()
   {
     //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&lt;iostream&gt;
import Lazy;

// A simple class called Resource
class Resource
{
  public:
  Resource()
  {
    std::cout&lt;&lt;"Welcome to new C++\n";
  }
  Resource(int a, int b)
  {
    std::cout&lt;&lt;"This also works : "&lt;&lt;a&lt;&lt;" "&lt;&lt;b&lt;&lt;"\n";
  }
  void func()
  {
    std::cout&lt;&lt;"Resource::func()\n";
  }

};

int main()
{
   gstd::Lazy&lt;Resource&gt;resx([](){ return Resource(4,5); });
   std::cout&lt;&lt;"Before construction\n";

   //Some code before using the resource

   resx-&gt;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?
Preface

I am using Apple Clang 10 and the following commands to build.

clang++ -std=c++17 -fmodules-ts --precompile Lazy.cppm -o Lazy.pcm
clang++ -std=c++17 -fmodules-ts -c Lazy.pcm -o Lazy.o
clang++ -std=c++17 -fmodules-ts -fprebuilt-module-path=. Lazy.o main.cpp


I'm using C++ 17 since that's the tag on the question, although I believe MSVC /std:c++latest corresponds to the parts of C++ 20 that are already implemented on MSVC.

I had one compilation error when I first tried this:

In file included from main.cpp:3:
Lazy.cppm:10:21: error: definition of 'optional' must be imported from module 'Lazy.&lt;global&gt;'
      before it is required
   std::optional&lt;T&gt; m_resource;
                    ^
main.cpp:26:24: note: in instantiation of template class 'gstd::Lazy&lt;Resource&gt;' requested here
   gstd::Lazy&lt;Resource&gt;resx([](){ return Resource(4,5); });


I solved it by adding #include &lt;optional&gt; in main.cpp, but maybe there's a better way.  Please let me know if there is a better solution.  I have only toyed around with modules so I'm far from an expert.

Fix your indentation

Minor nitpick: use consistent indentation.
You have 4 spaces for most of it (which is fine) but 1 space in a few spots.
And 0 spaces in a few spots too.  There are tools that can do this for you automatically (although it's pretty
easy to just do it by hand).

Consider using operator T

C++ can implicitly convert your object into a T:

template &lt;typename T&gt;
struct Lazy {
    operator const T&amp;() {
        ...
    }
};

int main() {
    Lazy&lt;int&gt; n(...);
    return n;
}


Consider making access const

When you access an object, you don't expect to modify it.  In other words, you should be able to write:

Lazy&lt;int&gt; const n(...);
int x = n + 2;


This implies an object that looks something like

template &lt;typename T&gt;
struct Lazy {
    operator const T&amp;() const {
        ...
    }
private:
    std::optional&lt;T&gt; mutable opt;
};


Think about what kind of functions you want to support

As you've written it now, you have two std::functions: the argument to the ctor and the one in the object.  You should at most have one.  You could use std::move.

Lazy(std::function&lt;T()&gt; ctor_func)
    : m_ctor_func(std::move(ctor_func)) // at least do this!
{}


At least use a member initializer list instead of initialization by assignment.

It may be preferable to get rid of std::function completely and instead use a template parameter.
This would allow you to get rid of all the copying.
You could even have non-copyable types in the function object.
You could even go overboard and deduce the stored type based on the templated function.  Then you could just write:

Lazy const n([nc=NonCopyable()]{ return 1; });


No template arguments!  It's up to you to decide whether this is a good idea, but it may be a good exercise if you
are new to templates.

Use optional::emplace

... instead of assignment.