# construct

First, we need a base definition for `make<T>`:

    template <class T> struct make
    {
      outcome::result<T> operator()() const noexcept
      {                                            //
        static_assert(!std::is_same<T, T>::value,  //
                      "make<T>() was not specialised for the type T supplied");
      }
    };

View this code on Github

This fails a static assert if the type is ever instantiated unspecialised.

We then specialise for `make<file_handle>`:

    template <> struct make<file_handle>
    {
      file_handle::path_type _path;
      file_handle::mode _mode{file_handle::mode::read};
      // Any other args, default initialised if necessary, follow here ...

      outcome::result<file_handle> operator()() const noexcept  //
      {
        return file_handle::file(std::move(_path));
      }
    };

View this code on Github

Because this is a struct, we can list initialise `make`, and use default member initialisers to implement default arguments. This can get you surprisingly far before you need to start writing custom constructors.

But in more complex code, you will usually provide all the initialisation overloads that you would for the constructors of your main type. You then implement a single phase 2 constructing function which accepts `make<YOURTYPE>` as input, and construct solely from that source.

Last revised: February 08, 2019 at 22:18:08 UTC