// ausgeliehen von Sones https://g...content-available-to-author-only...b.com/bingojamigo/VTMPL
#include <cstddef>
#include <limits>
#include <type_traits>

namespace vtmpl
{

using size_type = std::size_t;

using index_type = size_type;

template<typename T>
struct identity
{
    using type = T;
};

template<typename A, typename B>
struct type_pair : identity<type_pair<A,B>>
{
    using first = A;
    using second = B;
};

template <typename T, T...> struct value_list;

template <typename Type,
         Type... args>
struct value_list_base : identity<value_list<Type, args...>>
{
    static constexpr size_type length = sizeof...(args);

    static constexpr size_type npos = std::numeric_limits<size_type>::max();

    using value_type = Type;

    static constexpr value_type arr[] { args... };

private:

    static constexpr size_type _count_impl( char c, size_type index )
    {
        return arr[index] == c + (index == 0 ? 0 : _count_impl(c, index - 1));
    }

    static constexpr size_type _find_impl( char c, size_type index )
    {
        return index == length ? npos : c == arr[index] ? index : _find_impl(c, index + 1);
    }

public:

    static constexpr size_type count( char c )
    {
        return _count_impl( c, length - 1 );
    }

    static constexpr size_type find( char c )
    {
        return _find_impl( c, 0 );
    }
};

template <typename Type,
         Type... args>
constexpr Type value_list_base<Type, args...>::arr[];

template<typename Type,
         Type... args>
struct value_list : value_list_base<Type, args...> {};

template<char... args>
struct value_list<char, args...> : value_list_base<char, args...>
{
    static char constexpr nt_arr[] { args..., '\0' };
};

template<index_type ... args>
using index_list = value_list<index_type, args...>;

template <typename, typename> struct multiply;
template <index_type... indices, index_type... tail>
struct multiply<index_list<indices...>,
index_list<tail... >> : index_list<indices..., (sizeof...(indices)+indices)...,
           (2*sizeof...(indices)+indices)...,
           (3*sizeof...(indices)+indices)...,
           (4*sizeof...(indices)+tail)...> {};

//! make_index_list: Essential function to generate a list of numbers, used in many other functions to avoid recursion.
// Generates a list of natural numbers. make_index_list<4> -> {0, 1, 2, 3}, for example, and make_index_list<23510> -> {0, 1, 2, 3, 4, ..., 23509}.

template <index_type N>
struct make_index_list :
        multiply< typename make_index_list<N/4>::type,
        typename make_index_list<N%4>::type > {};

template <> struct make_index_list<3> : index_list<0, 1, 2> {};
template <> struct make_index_list<2> : index_list<0, 1> {};
template <> struct make_index_list<1> : index_list<0> {};
template <> struct make_index_list<0> : index_list<> {};

template<char... args>
char constexpr value_list<char, args...>::nt_arr[];

template <typename,
         size_type,
         size_type len,
         typename = typename make_index_list<len>::type> struct sub_list;

template <typename Type, Type ... args,
         size_type pos,
         size_type len,
         index_type... indices>
struct sub_list<value_list<Type, args...>,
        pos, len,
        index_list<indices...>> :
                             value_list<Type, value_list<Type, args...>::arr[pos + indices]...> {};

/// split_at: Splits the list into to sublists as specified by the position. The value at position pos is in the first list.

template <typename list,
         size_type pos> struct split_at;

template <typename val_t,
         val_t ... values,
         size_type pos>
struct split_at<value_list<val_t, values...>,
        pos> :
        type_pair< typename sub_list<value_list<val_t, values...>, 0, pos + 1>::type,
typename sub_list<value_list<val_t, values...>, pos + 1, sizeof...(values) - pos - 1>::type > {};

/// rtrim: cuts of all values after a specific one

template<typename List, typename List::value_type> struct rtrim;
template<typename Type, Type ... args, Type to_find>
struct rtrim<value_list<Type, args...>, to_find> :
        split_at<value_list<Type, args...>,
value_list<Type, args...>::find( to_find )>::first {};

template<char ... args>
using const_string = value_list<char, args...>;

#define SPLIT_1(s, x) ( x < sizeof(s) ? s[x] : '\0' )
#define SPLIT_4(s, x) SPLIT_1 (s, x), SPLIT_1 (s, x+1) , SPLIT_1 (s, x+2) , SPLIT_1 (s, x+3)
#define SPLIT_16(s, x) SPLIT_4 (s, x), SPLIT_4 (s, x+4) , SPLIT_4 (s, x+8) , SPLIT_4 (s, x+12)
#define SPLIT_64(s, x) SPLIT_16 (s, x), SPLIT_16 (s, x+16) , SPLIT_16 (s, x+32) , SPLIT_16 (s, x+48)
#define SPLIT_256(s, x) SPLIT_64 (s, x), SPLIT_64 (s, x+64) , SPLIT_64 (s, x+128 , SPLIT_64 (s, x+194)
#define SPLIT_1024(s, x) SPLIT_256(s, x), SPLIT_256(s, x+256), SPLIT_256(s, x+512), SPLIT_256(s, x+768)

//!: Use this macro to create a const_string from a string literal or constant pointer

#define STRING_IMPL(str, n) vtmpl::rtrim<vtmpl::const_string<SPLIT_##n(str, 0)>, '\0'>::type

#define STRING(str) STRING_IMPL(str, 64)
#define STRING_256(str) STRING_IMPL(str, 256)
#define STRING_1024(str) STRING_IMPL(str, 1024)

}
// ende ausgeliehen

#include <string>

namespace regex_impl
{    
// normales Zeichen
template <typename String>
class regex
{
public:
    static bool match(bool before, std::string string)
    {
        using string_pair = typename vtmpl::split_at<String, String::find('\0') - 1>::type;
        return regex<typename string_pair::second>::match(string.find(string_pair::first::nt_arr) != std::string::npos && before,
                                                          string);
    }
};

// Ende
template <>
class regex<vtmpl::const_string<'\0'>>
{
public:
    static bool match(bool before, std::string)
    {
        return before;
    }
};
}

template <typename Regex>
class regex
{
public:
    static bool match(std::string string)
    {
        return regex_impl::regex<Regex>::match(true, string);
    }
};

#include <iostream>

int main()
{
    std::cout << regex<STRING("ello")>::match("Hello World!")
    		  << regex<STRING("foo")>::match("Hello World!");
}