<commit_before>#include <iostream>
#include <experimental/optional>

using std::experimental::optional;
template <typename T>
struct NullableValue
{
  typedef optional<T> value;
};

template <typename T>
struct NullableValue<T*>
{
};

template <typename T>
struct NullableValue<std::unique_ptr<T>>
{
  typedef std::unique_ptr<T> value;
};

template <typename T>
struct NullableValue<std::shared_ptr<T>>
{
  typedef std::shared_ptr<T> value;
};

template <typename F,
          typename Value_T =
              std::remove_reference_t<decltype(std::declval<F>()())>>
class Lazy
{
  typedef typename NullableValue<Value_T>::value NullableValue_T;
  NullableValue_T m_value;
  F m_f;

public:
  Lazy(F f) : m_f(std::move(f)) {}
  auto& operator*()
  {
    init();
    return *m_value;
  }
  auto* operator -> ()
  {
    init();
    return &*m_value;
  }
  auto* get()
  {
    init();
    return &*m_value;
  }

private:
  void init()
  {
    if (!m_value)
    {
      m_value = m_f();
    }
  }
};

template <typename F>
auto make_lazy(F f)
{
  return Lazy<F>(std::move(f));
}

class MyClass
{
  int m_x = 0;

public:
  MyClass(int x) : m_x(x) {}
  int GetValue() { return m_x; }
};

int main(int argc, char* argv[])
{
  auto lX = make_lazy([]
                      {
                        std::cout << "Building" << std::endl;
                        return 5.9;
                      });

  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << std::endl;

  auto lptrX = make_lazy([]
                         {
                           std::cout << "Building" << std::endl;
                           return std::make_unique<MyClass>(5);
                         });

  std::cout << lptrX->GetValue() << std::endl;
  std::cout << lptrX->GetValue() << std::endl;
  std::cout << lptrX->GetValue() << std::endl;
  std::cout << lptrX->GetValue() << std::endl;
  std::cout << std::endl;

  auto f = [](MyClass* pM)
  {
    std::cout << "Called f" << std::endl;
  };

  f(lptrX.get());
}<commit_msg>Should be thread-safe<commit_after>#include <iostream>
#include <mutex>
#include <experimental/optional>

using std::experimental::optional;

template <typename Value_T>
class Lazy
{
  mutable optional<Value_T> m_value;
  mutable std::function<Value_T()> m_f;
  std::unique_ptr<std::mutex> m_mutex;

public:
  
  template<typename F>
  Lazy(F f) : m_f(std::move(f)), m_mutex(std::make_unique<std::mutex>()) {}

  Lazy(const Lazy&) = delete;
  Lazy& operator = (const Lazy&) = delete;

  Lazy(Lazy&&) = default;
  Lazy& operator = (Lazy&&) = default;
  
  auto& operator*()
  {
    init();
    return *m_value;
  }
  
  const auto& operator*() const
  {
    init();
    return *m_value;
  }
 
  auto* operator->()
  {
    init();
    return std::addressof(*m_value);
  }
  
  const auto* operator->() const
  {
    init();
    return std::addressof(*m_value);
  }

private:
  void init() const
  {
    std::lock_guard<std::mutex> l(*m_mutex);
    if ( ! m_value ) { m_value = m_f(); }
  }
};

template <typename F, typename T=decltype(std::declval<F&>()())>
auto make_lazy(F f)
{
  return Lazy<T>(std::move(f));
}

class MyClass
{
  int m_x = 0;

public:
  MyClass(int x) : m_x(x) {}
  int GetValue() { return m_x; }
};

int main(int argc, char* argv[])
{
  auto lX = make_lazy([]
                      {
                        std::cout << "Building" << std::endl;
                        return 5.9;
                      });

  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << *lX << std::endl;
  std::cout << std::endl;

  auto lClass = make_lazy([]
                         {
                           std::cout << "Building" << std::endl;
                           return MyClass(5);
                         });

  std::cout << lClass->GetValue() << std::endl;
  std::cout << lClass->GetValue() << std::endl;
  std::cout << lClass->GetValue() << std::endl;
  std::cout << lClass->GetValue() << std::endl;
  std::cout << std::endl;

  auto f = [](MyClass& pM)
  {
    std::cout << "Called f" << std::endl;
  };

  f(*lClass);
}
{'fraction_non_alphanumeric': 0.18555973659454375, 'fraction_numerical': 0.0018814675446848542, 'mean_word_length': 2.538269550748752, 'pattern_counts': {'":': 0, '<': 141, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6458262', 'n_tokens_mistral': 1582, 'n_tokens_neox': 1540, 'n_words': 321}