<commit_before>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

#ifndef FATAL_INCLUDE_fatal_type_list_h
#define FATAL_INCLUDE_fatal_type_list_h

#include <fatal/type/operation.h>
#include <fatal/type/pair.h>
#include <fatal/type/tag.h>
#include <fatal/type/transform.h>

#include <limits>
#include <type_traits>
#include <typeinfo>
#include <utility>

namespace fatal {

// TODO: ADD TESTS TO AVOID DOUBLE MOVES

/**
 * READ ME FIRST: You probably want to jump to
 * the line that says `type_list IMPLEMENTATION`
 */

///////////////////////////
// type_list DECLARATION //
///////////////////////////

template <typename...> struct type_list;

/////////////////////
// SUPPORT LIBRARY //
/////////////////////

//////////////
// type_get //
//////////////

/**
 * Specialization of `type_get_traits` so that `type_get` supports `type_list`.
 *
 * @author: <NAME> <<EMAIL>>
 */
template <typename... Args>
struct type_get_traits<type_list<Args...>> {
  template <std::size_t Index>
  using supported = std::integral_constant<bool, (Index < sizeof...(Args))>;

  template <std::size_t Index>
  using type = typename type_list<Args...>::template at<Index>;
};


////////////////////
// type_list_from //
////////////////////

/**
 * A convenience `type_list` builder based on transforms.
 * See members below for more info.
 *
 * @author: <NAME> <<EMAIL>>
 */
template <template <typename...> class... TTransforms>
struct type_list_from {
  /**
   * Creates a `type_list` from a given type `T` by applying a series of
   * transforms `TTransforms`.
   *
   * The resulting list will be comprised of the result of the transforms when
   * applied to `T`, in the order they are given.
   *
   * Example:
   *
   *  template <typename TFirst, typename TSecond, typename TThird>
   *  struct Foo {
   *    using first = TFirst;
   *    using second = TThird;
   *    using third = TThird;
   *  };
   *
   *  using foo = Foo<int, void, double>;
   *
   *  template <typename T> using get_first = typename T::first;
   *  template <typename T> using get_second = typename T::second;
   *  template <typename T> using get_third = typename T::third;
   *
   *  // yields `type_list<int, void, double>`
   *  using result = type_list_from<get_first, get_second, get_third>
   *    ::type<foo>;
   *
   * @author: <NAME> <<EMAIL>>
   */
  template <typename T>
  using type = type_list<TTransforms<T>...>;
};

/**
 * A convenience comparer implementation for `binary_search()` that compares a
 * variable against an `std::integral_constant`-like type.
 *
 * Returns `-1`, `0` or `1` when `lhs` is, respectively, less than, equal to or
 * greater than `RHS`.
 *
 * Example:
 *
 *  // `Index` is not important for this example, using `0`.
 *  template <int N>
 *  using rhs = indexed_type_tag<std::integral_constant<int, N>, 0>;
 *
 *  // yields `-1`
 *  type_value_comparer::compare(5, rhs<7>{});
 *
 *  // yields `0`
 *  type_value_comparer::compare(5, rhs<5>{});
 *
 *  // yields `1`
 *  type_value_comparer::compare(5, rhs<3>{});
 *
 * @author: <NAME> <<EMAIL>>
 */
struct type_value_comparer {
  template <typename TLHS, typename TRHS, std::size_t Index>
  static constexpr int compare(TLHS &&lhs, indexed_type_tag<TRHS, Index>) {
    return lhs < TRHS::value
      ? -1
      : TRHS::value < lhs
        ? 1
        : 0;
  }
};

/**
 * A convenience comparer implementation for `binary_search()` that compares a
 * variable against the `indexed_type_tag`'s `Index`.
 *
 * Returns `-1`, `0` or `1` when `lhs` is, respectively, less than, equal to or
 * greater than `RHS`.
 *
 * Example:
 *
 *  // `T` is not important for this example, using `void`.
 *  template <std::size_t Index>
 *  using rhs = indexed_type_tag<void, Index>;
 *
 *  // yields `-1`
 *  type_value_comparer::compare(5, rhs<7>{});
 *
 *  // yields `0`
 *  type_value_comparer::compare(5, rhs<5>{});
 *
 *  // yields `1`
 *  type_value_comparer::compare(5, rhs<3>{});
 *
 * @author: <NAME> <<EMAIL>>
 */
struct index_value_comparer {
  template <typename TLHS, typename TRHS, std::size_t Index>
  static constexpr int compare(TLHS &&lhs, indexed_type_tag<TRHS, Index>) {
    return lhs < Index
      ? -1
      : Index < lhs
        ? 1
        : 0;
  }
};

/**
 * A convenience visitor that accpets any parameters and does nothing.
 *
 * @author: <NAME> <<EMAIL>>
 */
struct no_op_visitor {
  template <typename... UArgs>
  void operator ()(UArgs &&...) {}
};

////////////////////////////
// IMPLEMENTATION DETAILS //
////////////////////////////

namespace detail {
namespace type_list_impl {

////////
// at //
////////

template <std::size_t, typename...> struct at;

template <std::size_t Distance, typename U, typename... UArgs>
struct at<Distance, U, UArgs...> {
  using type = typename at<Distance - 1, UArgs...>::type;
};

template <typename U, typename... UArgs>
struct at<0, U, UArgs...> {
  using type = U;
};<commit_msg>- reminder to reorganize headers<commit_after>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

#ifndef FATAL_INCLUDE_fatal_type_list_h
#define FATAL_INCLUDE_fatal_type_list_h

#include <fatal/type/operation.h>
#include <fatal/type/pair.h>
#include <fatal/type/tag.h>
#include <fatal/type/transform.h>

#include <limits>
#include <type_traits>
#include <typeinfo>
#include <utility>

namespace fatal {

// TODO: ADD TESTS TO AVOID DOUBLE MOVES

/**
 * READ ME FIRST: You probably want to jump to
 * the line that says `type_list IMPLEMENTATION`
 */

///////////////////////////
// type_list DECLARATION //
///////////////////////////

template <typename...> struct type_list;

/////////////////////
// SUPPORT LIBRARY //
/////////////////////

//////////////
// type_get //
//////////////

/**
 * Specialization of `type_get_traits` so that `type_get` supports `type_list`.
 *
 * @author: <NAME> <<EMAIL>>
 */
template <typename... Args>
struct type_get_traits<type_list<Args...>> {
  template <std::size_t Index>
  using supported = std::integral_constant<bool, (Index < sizeof...(Args))>;

  template <std::size_t Index>
  using type = typename type_list<Args...>::template at<Index>;
};


////////////////////
// type_list_from //
////////////////////

/**
 * A convenience `type_list` builder based on transforms.
 * See members below for more info.
 *
 * @author: <NAME> <<EMAIL>>
 */
template <template <typename...> class... TTransforms>
struct type_list_from {
  /**
   * Creates a `type_list` from a given type `T` by applying a series of
   * transforms `TTransforms`.
   *
   * The resulting list will be comprised of the result of the transforms when
   * applied to `T`, in the order they are given.
   *
   * Example:
   *
   *  template <typename TFirst, typename TSecond, typename TThird>
   *  struct Foo {
   *    using first = TFirst;
   *    using second = TThird;
   *    using third = TThird;
   *  };
   *
   *  using foo = Foo<int, void, double>;
   *
   *  template <typename T> using get_first = typename T::first;
   *  template <typename T> using get_second = typename T::second;
   *  template <typename T> using get_third = typename T::third;
   *
   *  // yields `type_list<int, void, double>`
   *  using result = type_list_from<get_first, get_second, get_third>
   *    ::type<foo>;
   *
   * @author: <NAME> <<EMAIL>>
   */
  template <typename T>
  using type = type_list<TTransforms<T>...>;
};

/**
 * A convenience comparer implementation for `binary_search()` that compares a
 * variable against an `std::integral_constant`-like type.
 *
 * Returns `-1`, `0` or `1` when `lhs` is, respectively, less than, equal to or
 * greater than `RHS`.
 *
 * Example:
 *
 *  // `Index` is not important for this example, using `0`.
 *  template <int N>
 *  using rhs = indexed_type_tag<std::integral_constant<int, N>, 0>;
 *
 *  // yields `-1`
 *  type_value_comparer::compare(5, rhs<7>{});
 *
 *  // yields `0`
 *  type_value_comparer::compare(5, rhs<5>{});
 *
 *  // yields `1`
 *  type_value_comparer::compare(5, rhs<3>{});
 *
 * @author: <NAME> <<EMAIL>>
 */
// TODO: MOVE TO ANOTHER HEADER
struct type_value_comparer {
  template <typename TLHS, typename TRHS, std::size_t Index>
  static constexpr int compare(TLHS &&lhs, indexed_type_tag<TRHS, Index>) {
    return lhs < TRHS::value
      ? -1
      : TRHS::value < lhs
        ? 1
        : 0;
  }
};

/**
 * A convenience comparer implementation for `binary_search()` that compares a
 * variable against the `indexed_type_tag`'s `Index`.
 *
 * Returns `-1`, `0` or `1` when `lhs` is, respectively, less than, equal to or
 * greater than `RHS`.
 *
 * Example:
 *
 *  // `T` is not important for this example, using `void`.
 *  template <std::size_t Index>
 *  using rhs = indexed_type_tag<void, Index>;
 *
 *  // yields `-1`
 *  type_value_comparer::compare(5, rhs<7>{});
 *
 *  // yields `0`
 *  type_value_comparer::compare(5, rhs<5>{});
 *
 *  // yields `1`
 *  type_value_comparer::compare(5, rhs<3>{});
 *
 * @author: <NAME> <<EMAIL>>
 */
// TODO: MOVE TO ANOTHER HEADER
struct index_value_comparer {
  template <typename TLHS, typename TRHS, std::size_t Index>
  static constexpr int compare(TLHS &&lhs, indexed_type_tag<TRHS, Index>) {
    return lhs < Index
      ? -1
      : Index < lhs
        ? 1
        : 0;
  }
};

/**
 * A convenience visitor that accpets any parameters and does nothing.
 *
 * @author: <NAME> <<EMAIL>>
 */
// TODO: MOVE TO ANOTHER HEADER
struct no_op_visitor {
  template <typename... UArgs>
  void operator ()(UArgs &&...) {}
};

////////////////////////////
// IMPLEMENTATION DETAILS //
////////////////////////////

namespace detail {
namespace type_list_impl {

////////
// at //
////////

template <std::size_t, typename...> struct at;

template <std::size_t Distance, typename U, typename... UArgs>
struct at<Distance, U, UArgs...> {
  using type = typename at<Distance - 1, UArgs...>::type;
};

template <typename U, typename... UArgs>
struct at<0, U, UArgs...> {
  using type = U;
};
{'fraction_non_alphanumeric': 0.18585005279831046, 'fraction_numerical': 0.007295766535470865, 'mean_word_length': 2.728704366499642, 'pattern_counts': {'":': 0, '<': 153, '<?xml version=': 0, '>': 143, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2081890', 'n_tokens_mistral': 3533, 'n_tokens_neox': 3390, 'n_words': 1009}