<commit_before>#ifndef GCL_TMP_H_
# define GCL_TMP_H_

namespace GCL
{
    namespace TMP
    {
		template <class T, class ...Classes>
		struct Super
		{
			struct Type : T, Super<Classes...>::Type
			{};
		};
		template <class T>
		struct Super<T>
		{
			using Type = T;
		};

        struct NullType {};

		template <bool condition, typename _THEN, typename _ELSE>	struct IF
        {};
		template <typename _THEN, typename _ELSE>					struct IF<true, _THEN, _ELSE>
        {
            using _Type = _THEN;
        };
		template <typename _THEN, typename _ELSE>					struct IF<false, _THEN, _ELSE>
        {
            using _Type = _ELSE;
        };

        template <size_t _pID = 0>
        struct List
        {
            static constexpr size_t _ID = _pID;

            using _ThisType = List<_ID>;
            using _Next = List<_ID + 1>;
            using _PREV = TMP::IF<(_ID == 0), TMP::NullType, List<_ID - 1> >;
        };

		// [Todo] : Refactoring
        template <typename Type, template <typename> class Visitor, size_t _ItMax, size_t _It = 0, bool Continue = true>
        struct For
        {
            static void    iterate()
            {
                Visitor<Type>::visit();
                For<Type::_Next, Visitor, _ItMax, _It + 1, (_It < _ItMax)>::iterate();
            }

        };
        template <typename Type, template <typename> class Visitor, size_t _ItMax, size_t _It>
        struct For<Type, Visitor, _ItMax, _It, false>
        {
            static void    iterate() {}
        };

		template <typename ... T>				struct Foreach;
		template <typename T0, typename ... T>	struct Foreach<T0, T...>
		{
			Foreach() = delete;
			Foreach(const Foreach &) = delete;
			Foreach(const Foreach &&) = delete;

			template <template <typename> class T_Functor>
			static void	Call(void)
			{
				T_Functor<T0>::Call();
				Foreach<T...>::Call<T_Functor>();
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static void	CallAt(const size_t pos)
			{
				if (N == pos)	T_Functor<T0>::Call();
				else			Foreach<T...>::CallAt<T_Functor, (N + 1)>(pos);
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static typename T_Functor<T0>::return_type	CallAt_withReturn(const size_t pos)
			{
				if (N == pos)	return T_Functor<T0>::Call();
				else			return Foreach<T...>::CallAt_withReturn<T_Functor, (N + 1)>(pos);
			}
		};
		template <>								struct Foreach<>
		{
			Foreach() = delete;
			Foreach(const Foreach &) = delete;
			Foreach(const Foreach &&) = delete;

			template <template <typename> class T_Functor>
			static void	Call(void)
			{}
			template <template <typename> class T_Functor, size_t N = 0>
			static void	CallAt(const size_t pos)
			{
				throw std::out_of_range("template <typename ... T> struct Foreach::CallAt");
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static typename T_Functor<void>::return_type	CallAt_withReturn(const size_t pos)
			{
				throw std::out_of_range("template <typename ... T> struct Foreach::CallAt_withReturn");
			}
		};

		template <typename ...T>
		struct TypeContainer
		{
			using _Types = std::tuple<T...>;

			template <std::size_t N>
			using TypeAt = typename std::tuple_element<N, _Types>::type;
			// using TypeAt = std::remove_reference<decltype(std::get<N>(tuple))>::type
			using Index_type = size_t;
			template <typename T_Search>
			constexpr static const Index_type IndexOf(void)
			{
				return GCL::TypeTrait::IndexOf< T_Search, _Types>::value;
			}
		};

        struct Test
        {
            template <typename T>
            struct Visitor_ListIdPrinter
            {
                static void visit()
                {
					std::cout << T::_ID << ' ';
                }
            };

            static bool    Proceed()
            {
				std::cout << "\t |- Generated ID list : ";
                TMP::For<TMP::List<>, Visitor_ListIdPrinter, 10>::iterate();
				std::cout << std::endl;

				struct A {}; struct B {}; struct C {};
				using _Types = typename TypeContainer
					<
					A
					, B
					, C
					>;<commit_msg>new feature : GCL::TMP::Foreach<...>::Require / constraint, static type check<commit_after>#ifndef GCL_TMP_H_
# define GCL_TMP_H_

namespace GCL
{
    namespace TMP
    {
		template <class T, class ...Classes>
		struct Super
		{
			struct Type : T, Super<Classes...>::Type
			{};
		};
		template <class T>
		struct Super<T>
		{
			using Type = T;
		};

        struct NullType {};

		template <bool condition, typename _THEN, typename _ELSE>	struct IF
        {};
		template <typename _THEN, typename _ELSE>					struct IF<true, _THEN, _ELSE>
        {
            using _Type = _THEN;
        };
		template <typename _THEN, typename _ELSE>					struct IF<false, _THEN, _ELSE>
        {
            using _Type = _ELSE;
        };

        template <size_t _pID = 0>
        struct List
        {
            static constexpr size_t _ID = _pID;

            using _ThisType = List<_ID>;
            using _Next = List<_ID + 1>;
            using _PREV = TMP::IF<(_ID == 0), TMP::NullType, List<_ID - 1> >;
        };

		// [Todo] : Refactoring
        template <typename Type, template <typename> class Visitor, size_t _ItMax, size_t _It = 0, bool Continue = true>
        struct For
        {
            static void    iterate()
            {
                Visitor<Type>::visit();
                For<Type::_Next, Visitor, _ItMax, _It + 1, (_It < _ItMax)>::iterate();
            }

        };
        template <typename Type, template <typename> class Visitor, size_t _ItMax, size_t _It>
        struct For<Type, Visitor, _ItMax, _It, false>
        {
            static void    iterate() {}
        };

		template <typename ... T>				struct Foreach;
		template <typename T0, typename ... T>	struct Foreach<T0, T...>
		{
			Foreach() = delete;
			Foreach(const Foreach &) = delete;
			Foreach(const Foreach &&) = delete;

			template <template <typename> class T_Constraint>
			struct Require
			{
				T_Constraint<T0> _check;
				typename Foreach<T...>::template Require<T_Constraint> _next;
			};
			template <template <typename> class T_Functor>
			static void	Call(void)
			{
				T_Functor<T0>::Call();
				Foreach<T...>::Call<T_Functor>();
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static void	CallAt(const size_t pos)
			{
				if (N == pos)	T_Functor<T0>::Call();
				else			Foreach<T...>::CallAt<T_Functor, (N + 1)>(pos);
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static typename T_Functor<T0>::return_type	CallAt_withReturn(const size_t pos)
			{
				if (N == pos)	return T_Functor<T0>::Call();
				else			return Foreach<T...>::CallAt_withReturn<T_Functor, (N + 1)>(pos);
			}
		};
		template <>								struct Foreach<>
		{
			Foreach() = delete;
			Foreach(const Foreach &) = delete;
			Foreach(const Foreach &&) = delete;

			template <template <typename> class T_Constraint>
			struct Require
			{};
			template <template <typename> class T_Functor>
			static void	Call(void)
			{}
			template <template <typename> class T_Functor, size_t N = 0>
			static void	CallAt(const size_t pos)
			{
				throw std::out_of_range("template <typename ... T> struct Foreach::CallAt");
			}
			template <template <typename> class T_Functor, size_t N = 0>
			static typename T_Functor<void>::return_type	CallAt_withReturn(const size_t pos)
			{
				throw std::out_of_range("template <typename ... T> struct Foreach::CallAt_withReturn");
			}
		};

		template <typename ...T>
		struct TypeContainer
		{
			using _Types = std::tuple<T...>;

			template <std::size_t N>
			using TypeAt = typename std::tuple_element<N, _Types>::type;
			// using TypeAt = std::remove_reference<decltype(std::get<N>(tuple))>::type
			using Index_type = size_t;
			template <typename T_Search>
			constexpr static const Index_type IndexOf(void)
			{
				return GCL::TypeTrait::IndexOf< T_Search, _Types>::value;
			}
		};

        struct Test
        {
            template <typename T>
            struct Visitor_ListIdPrinter
            {
                static void visit()
                {
					std::cout << T::_ID << ' ';
                }
            };

			struct A
			{
				struct _MandatoryNested {};
			};
			struct B
			{
				struct _MandatoryNested {};
			};
			struct C
			{
				struct _MandatoryNested {};
			};
			
			template <typename T>
			struct T_Constraint
			{
				using _MandatoryNested = typename T::_MandatoryNested;
			};

            static bool    Proceed()
            {
				// static require constraint
				(void)TMP::Foreach<A, B, C>::template Require<T_Constraint>();

				std::cout << "\t |- Generated ID list : ";
                TMP::For<TMP::List<>, Visitor_ListIdPrinter, 10>::iterate();
				std::cout << std::endl;

				using _Types = typename TypeContainer
					<
					A
					, B
					, C
					>;
{'fraction_non_alphanumeric': 0.12810987279072386, 'fraction_numerical': 0.004615557807047169, 'mean_word_length': 2.3310836145481817, 'pattern_counts': {'":': 0, '<': 158, '<?xml version=': 0, '>': 140, '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': '4491264', 'n_tokens_mistral': 3433, 'n_tokens_neox': 2895, 'n_words': 734}