What should I do to check whether an integer array is palindrome (e.g. 1 3 10 3 1 is palindrome) in compile time?
A possible framework could be:
template <int...>
class IntArray;
template <int... values>
class Palindrome<IntArray<values...>>;
static_assert(Palindrome<IntArray<1, 2, 1>>::check == true);
I know this question seems to be meaningless but I'm just curious about the grammar that I should use.
I've read posts and blogs about compile-time Fibonacci calculation but found nothing inspiring.
Could anyone tell me how to implement this?
I know little about compile-time programming; the most complicated problem that I can tackle with compile-time programming is like this:
template<int a, int b>
struct max_template {
static constexpr int value = a > b ? a : b;
};
constexpr int max_fun(int a, int b) {
return a > b ? a : b;
}
// or
template <unsigned N>
struct Fibonacci
{
enum
{
value = Fibonacci<N-1>::value + Fibonacci<N-2>::value
};
};
template <>
struct Fibonacci<1>
{
enum
{
value = 1
};
};
template <>
struct Fibonacci<0>
{
enum
{
value = 0
};
};
It's more or less trivial in C++17 unless you have a limitation to use purely functional constructs:
template<int...>
class IntArray;
template<class>
struct IsPalindrome;
template<int... values>
struct IsPalindrome<IntArray<values...>> {
static constexpr bool value = []{
constexpr int arr[] = {values...};
constexpr std::size_t N = std::size(arr);
for (std::size_t i = 0; i < N / 2; ++i)
if (arr[i] != arr[N - 1 - i])
return false;
return true;
}();
};
static_assert( IsPalindrome<IntArray<0, 1, 2, 3, 2, 1, 0>>::value);
static_assert(!IsPalindrome<IntArray<0, 1, 2, 3, 4, 1, 0>>::value);
Purely functional implementation is more lengthy but works even in C++11:
template<class IntArray, int>
struct PushBack;
template<int... values, int value>
struct PushBack<IntArray<values...>, value> {
using type = IntArray<values..., value>;
};
template<class IntArray>
struct Reverse;
template<>
struct Reverse<IntArray<>> {
using type = IntArray<>;
};
template<int first, int... rest>
struct Reverse<IntArray<first, rest...>> {
using type = typename PushBack<
typename Reverse<IntArray<rest...>>::type,
first
>::type;
};
template<class IntArray>
using IsPalindrome =
std::is_same<IntArray, typename Reverse<IntArray>::type>;