<commit_before>#ifndef INCLUDED_TOBY_VARIANT_H
#define INCLUDED_TOBY_VARIANT_H

#include "overload_set.hpp"

#include <cstddef>
#include <experimental/type_traits>
#include <stdexcept>

#include <spdlog/sinks/null_sink.h>
#include <spdlog/spdlog.h>

namespace toby {
namespace detail {
inline auto logger() {
  auto l = spdlog::get("variant");
  if (l) {
    return l;
  }
  return spdlog::create("variant",
                        spdlog::sink_ptr(new spdlog::sinks::null_sink_st()));
}

template <typename I, I N, typename... Ts>
struct variant_construct;

template <typename I, I N>
struct variant_construct<I, N> {
  static I construct();
};

template <typename I, I N, typename T, typename... Ts>
struct variant_construct<I, N, T, Ts...>
    : private variant_construct<I, N + 1, Ts...> {
  using super = variant_construct<I, N + 1, Ts...>;

  static_assert(!std::experimental::disjunction<std::is_same<T, Ts>...>::value,
                "types must be unique");

  static I construct(void* storage, const T& value) {
    logger()->debug() << "copy construct<" << N << ">";
    new (storage) T(value);
    return N;
  }
  static I construct(void* storage, T&& value) {
    logger()->debug() << "move construct<" << N << ">";
    new (storage) T(std::forward<T>(value));
    return N;
  }
  using super::construct;
};

template <typename I, I N, typename... Ts>
struct variant_visit;

template <typename I, I N>
struct variant_visit<I, N> {<commit_msg>Revert "variant: enforce unique types"<commit_after>#ifndef INCLUDED_TOBY_VARIANT_H
#define INCLUDED_TOBY_VARIANT_H

#include "overload_set.hpp"

#include <cstddef>
#include <stdexcept>

#include <spdlog/sinks/null_sink.h>
#include <spdlog/spdlog.h>

namespace toby {
namespace detail {
inline auto logger() {
  auto l = spdlog::get("variant");
  if (l) {
    return l;
  }
  return spdlog::create("variant",
                        spdlog::sink_ptr(new spdlog::sinks::null_sink_st()));
}

template <typename I, I N, typename... Ts>
struct variant_construct;

template <typename I, I N>
struct variant_construct<I, N> {
  static I construct();
};

template <typename I, I N, typename T, typename... Ts>
struct variant_construct<I, N, T, Ts...>
    : private variant_construct<I, N + 1, Ts...> {
  using super = variant_construct<I, N + 1, Ts...>;

  static I construct(void* storage, const T& value) {
    logger()->debug() << "copy construct<" << N << ">";
    new (storage) T(value);
    return N;
  }
  static I construct(void* storage, T&& value) {
    logger()->debug() << "move construct<" << N << ">";
    new (storage) T(std::forward<T>(value));
    return N;
  }
  using super::construct;
};

template <typename I, I N, typename... Ts>
struct variant_visit;

template <typename I, I N>
struct variant_visit<I, N> {
{'fraction_non_alphanumeric': 0.16192875134940626, 'fraction_numerical': 0.0014393666786613889, 'mean_word_length': 3.86013986013986, 'pattern_counts': {'":': 0, '<': 64, '<?xml version=': 0, '>': 44, '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': '4076718', 'n_tokens_mistral': 989, 'n_tokens_neox': 966, 'n_words': 266}