<commit_before>// Copyright (c) 2019 <NAME> and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#ifndef OVK_CORE_MAP_HPP_INCLUDED
#define OVK_CORE_MAP_HPP_INCLUDED

#include <ovk/core/Array.hpp>
#include <ovk/core/ArrayTraits.hpp>
#include <ovk/core/Global.hpp>
#include <ovk/core/IteratorTraits.hpp>
#include <ovk/core/PointerIterator.hpp>
#include <ovk/core/Requires.hpp>
#include <ovk/core/Set.hpp>
#include <ovk/core/TypeTraits.hpp>

#include <algorithm>
#include <functional>
#include <initializer_list>
#include <memory>
#include <type_traits>
#include <utility>

namespace ovk {

namespace map_internal {

template <typename T, bool Contiguous> class value_wrapper;

template <typename T> class value_wrapper<T, true> {

public:

  value_wrapper(const T &Value):
    Value_(Value)
  {}

  value_wrapper(T &&Value):
    Value_(std::move(Value))
  {}

  template <typename... Args, OVK_FUNCTION_REQUIRES(std::is_constructible<T, Args &&...>::value &&
    !core::IsCopyOrMoveArgument<T, Args &&...>())> value_wrapper(Args &&... Arguments):
    Value_(std::forward<Args>(Arguments)...)
  {}

  value_wrapper(const value_wrapper &Other) = default;
  value_wrapper(value_wrapper &&Other) noexcept = default;
  value_wrapper &operator=(const value_wrapper &Other) = default;
  value_wrapper &operator=(value_wrapper &&Other) noexcept = default;

  const T &Get() const { return Value_; }
  T &Get() { return Value_; }

private:

  T Value_;

};

template <typename T> class value_wrapper<T, false> {

public:

  value_wrapper(const T &Value):
    Value_(new T(Value))
  {}

  value_wrapper(T &&Value):
    Value_(new T(std::move(Value)))
  {}

  template <typename... Args, OVK_FUNCTION_REQUIRES(std::is_constructible<T, Args &&...>::value &&
    !core::IsCopyOrMoveArgument<T, Args &&...>())> value_wrapper(Args &&... Arguments):
    Value_(new T(std::forward<Args>(Arguments)...))
  {}

  value_wrapper(const value_wrapper &Other):
    Value_(new T(*Other.Value_))
  {}

  value_wrapper(value_wrapper &&Other) noexcept:
    Value_(std::move(Other.Value_))
  {}

  value_wrapper &operator=(value_wrapper Other) noexcept {
    using std::swap;
    swap(Value_, Other.Value_);
    return *this;
  }

  const T &Get() const { return *Value_; }
  T &Get() { return *Value_; }

private:

  std::unique_ptr<T> Value_;

};

}

template <typename T> constexpr bool MapContiguousDefault() {
  // 16 seems like a good number *shrug*
  return sizeof(T) <= 16;
}

template <typename KeyType, typename ValueType, bool Contiguous_=MapContiguousDefault<ValueType>()><commit_msg>don't use contiguous map storage for types that aren't noexcept movable (like std::string)<commit_after>// Copyright (c) 2019 <NAME> and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#ifndef OVK_CORE_MAP_HPP_INCLUDED
#define OVK_CORE_MAP_HPP_INCLUDED

#include <ovk/core/Array.hpp>
#include <ovk/core/ArrayTraits.hpp>
#include <ovk/core/Global.hpp>
#include <ovk/core/IteratorTraits.hpp>
#include <ovk/core/PointerIterator.hpp>
#include <ovk/core/Requires.hpp>
#include <ovk/core/Set.hpp>
#include <ovk/core/TypeTraits.hpp>

#include <algorithm>
#include <functional>
#include <initializer_list>
#include <memory>
#include <type_traits>
#include <utility>

namespace ovk {

namespace map_internal {

template <typename T, bool Contiguous> class value_wrapper;

template <typename T> class value_wrapper<T, true> {

public:

  value_wrapper(const T &Value):
    Value_(Value)
  {}

  value_wrapper(T &&Value):
    Value_(std::move(Value))
  {}

  template <typename... Args, OVK_FUNCTION_REQUIRES(std::is_constructible<T, Args &&...>::value &&
    !core::IsCopyOrMoveArgument<T, Args &&...>())> value_wrapper(Args &&... Arguments):
    Value_(std::forward<Args>(Arguments)...)
  {}

  value_wrapper(const value_wrapper &Other) = default;
  value_wrapper(value_wrapper &&Other) noexcept = default;
  value_wrapper &operator=(const value_wrapper &Other) = default;
  value_wrapper &operator=(value_wrapper &&Other) noexcept = default;

  const T &Get() const { return Value_; }
  T &Get() { return Value_; }

private:

  T Value_;

};

template <typename T> class value_wrapper<T, false> {

public:

  value_wrapper(const T &Value):
    Value_(new T(Value))
  {}

  value_wrapper(T &&Value):
    Value_(new T(std::move(Value)))
  {}

  template <typename... Args, OVK_FUNCTION_REQUIRES(std::is_constructible<T, Args &&...>::value &&
    !core::IsCopyOrMoveArgument<T, Args &&...>())> value_wrapper(Args &&... Arguments):
    Value_(new T(std::forward<Args>(Arguments)...))
  {}

  value_wrapper(const value_wrapper &Other):
    Value_(new T(*Other.Value_))
  {}

  value_wrapper(value_wrapper &&Other) noexcept:
    Value_(std::move(Other.Value_))
  {}

  value_wrapper &operator=(value_wrapper Other) noexcept {
    using std::swap;
    swap(Value_, Other.Value_);
    return *this;
  }

  const T &Get() const { return *Value_; }
  T &Get() { return *Value_; }

private:

  std::unique_ptr<T> Value_;

};

}

template <typename T> constexpr bool MapContiguousDefault() {
  // 16 seems like a good number *shrug*
  return sizeof(T) <= 16 && std::is_nothrow_move_constructible<T>::value &&
    std::is_nothrow_move_assignable<T>::value;
}

template <typename KeyType, typename ValueType, bool Contiguous_=MapContiguousDefault<ValueType>()>
{'fraction_non_alphanumeric': 0.1530993278566094, 'fraction_numerical': 0.002987303958177745, 'mean_word_length': 4.906284454244763, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 69, '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': '2922425', 'n_tokens_mistral': 1862, 'n_tokens_neox': 1809, 'n_words': 399}