とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

template と constexpr を使った何をしたいのかよく分からなくなった Hello, world

#include<cstddef>
#include<iostream>

template<std::size_t N>
struct c_string
{
 char elems[N ? N : 1];
 constexpr char const * c_str()const{return elems;}
};

template<std::size_t...>
struct index_tuple
{};

template<std::size_t S, std::size_t F, class Acc = index_tuple<>, bool B = S >= F>
struct index_range
{
 typedef Acc type;
};

template<std::size_t S, std::size_t F, std::size_t... Indexes>
struct index_range<S, F, index_tuple<Indexes...>, false>
 : index_range<S + 1, F, index_tuple<Indexes..., S> >
{};

template<class T, std::size_t M, std::size_t N, std::size_t... Indexes1, std::size_t... Indexes2>
constexpr c_string<(M - 1) + (N - 1) + 1> strcat_impl(T const (&a)[M], index_tuple<Indexes1...>,
                                                      T const (&b)[N], index_tuple<Indexes2...>)
{
 return {{a[Indexes1]..., b[Indexes2]..., '\0'}};
}

template<std::size_t M, std::size_t N>
constexpr c_string<(M - 1) + (N - 1) + 1> strcat(char const (&a)[M], char const (&b)[N])
{
 return strcat_impl(a, typename index_range<0, M - 1>::type(), b, typename index_range<0, N - 1>::type());
}

template<std::size_t N>
constexpr auto size(char const (& a)[N]) -> decltype(sizeof(a))
{
 return sizeof(a);
}

template<class T, class U>
struct cat
{
 static constexpr std::size_t value_size = size(T::value) - 1 + size(U::value) - 1 + 1;
 static constexpr c_string<value_size> value = strcat(T::value, U::value);
};

//////////

struct hello
{
 static constexpr char value[] = "Hello, ";
};

struct world
{
 static constexpr char value[] = "world";
};

int main()
{
 constexpr auto hello_world = cat<hello, world>::value;
 std::cout << hello_world.c_str() << std::endl;
}

実行結果

Hello, world