text: namespace hfsm2 {
  namespace detail {
  
  ////////////////////////////////////////////////////////////////////////////////
  // SPECIFIC
  
  template <typename... Ts>
  struct TL_ final {
  	static constexpr Long SIZE = sizeof...(Ts);
  };
  
  // SPECIFIC
  //------------------------------------------------------------------------------
  
  template <Long N>
  struct Const {
  	static constexpr Long VALUE = N;
  };
  
  //------------------------------------------------------------------------------
  
  template <typename, typename>
  struct PrependT;
  
  template <typename T, typename... Ts>
  struct PrependT<T, TL_<Ts...>> final {
  	using Type = TL_<T, Ts...>;
  };
  
  template <typename... Ts>
  using PrependTypes = typename PrependT<Ts...>::Type;
  
  //------------------------------------------------------------------------------
  
  template <typename, typename>
  struct MergeT;
  
  template <typename... Ts1, typename... Ts2>
  struct MergeT<TL_<Ts1...>, TL_<Ts2...>> final {
  	using Type = TL_<Ts1..., Ts2...>;
  };
  
  template <typename... Ts>
  using Merge = typename MergeT<Ts...>::Type;
  
  //------------------------------------------------------------------------------
  
  template <Long, Long, typename...>
  struct LowerT;
  
  template <Long NHalf, Long NIndex, typename... Ts>
  using LowerTypes = typename LowerT<NHalf, NIndex, Ts...>::Type;
  
  template <Long NHalf, Long NIndex, typename TFirst, typename... TRest>
  struct LowerT<NHalf, NIndex, TFirst, TRest...> final {
  	using LTypeList = typename LowerT<NHalf, NIndex + 1, TRest...>::Type;
  
  	using Type = Conditional<
  					 (NIndex < NHalf),
  					 PrependTypes<TFirst, LTypeList>,
  					 LTypeList
  				 >;
  };
  
  template <Long NHalf, Long NIndex>
  struct LowerT<NHalf, NIndex> final {
  	using Type = TL_<>;
  };
  
  template <typename... Ts>
  using LHalfTypes = LowerTypes<sizeof...(Ts) / 2, 0, Ts...>;
  
  //------------------------------------------------------------------------------
  
  template <Long, Long, typename...>
  struct UpperT;
  
  template <Long NHalf, Long NIndex, typename... Ts>
  using UpperTypes = typename UpperT<NHalf, NIndex, Ts...>::Type;
  
  template <Long NHalf, Long NIndex, typename TFirst, typename... TRest>
  struct UpperT<NHalf, NIndex, TFirst, TRest...> final {
  	using Type = Conditional<
  					 (NIndex < NHalf),
  					 UpperTypes<NHalf, NIndex + 1, TRest...>,
  					 TL_<TFirst, TRest...>
  				 >;
  };
  
  template <Long NHalf, Long NIndex>
  struct UpperT<NHalf, NIndex> final {
  	using Type = TL_<>;
  };
  
  template <typename... Ts>
  using RHalfTypes = UpperTypes<sizeof...(Ts) / 2, 0, Ts...>;
  
  //------------------------------------------------------------------------------
  
  template<Long, typename...>
  struct FindImpl
  	: Const<INVALID_LONG>
  {};
  
  template<Long N, typename T, typename TFirst, typename... TRest>
  struct FindImpl<N, T, TFirst, TRest...>
  	: FindImpl<N + 1, T, TRest...>
  {};
  
  template<Long N, typename T, typename... Ts>
  struct FindImpl<N, T, T, Ts...>
  	: Const<N>
  {};
  
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  template <typename, typename>
  struct Find;
  
  template <typename T, typename... Ts>
  struct Find<TL_<Ts...>, T> final
  	: FindImpl<0, T, Ts...>
  {};
  
  ////////////////////////////////////////////////////////////////////////////////
  // SPECIFIC
  
  }
  
  template <typename TList, typename T>
  constexpr Long index   () noexcept { return detail::Find<TList, T>::VALUE;		}
  
  template <typename TList, typename T>
  constexpr bool contains() noexcept { return index<TList, T>() != INVALID_LONG;	}
  
  // SPECIFIC
  //------------------------------------------------------------------------------
  
  }
  