# Meta functions for sequences of exponents of 2

I have implemented some meta functions to create sequence for exponents of 2. I would love to know if there is any way to make the code more optimized.

Note: int main() should not be modified. From the requirements of my school:

This program must implement three definitions: sequence<Ts...>, print() and printing_type().

Hence, the name of functions should not be modified.

#include<iostream>

template<size_t... Ts>
struct int_seq{};

template<size_t TCount, size_t...Ts>
struct sequence
{
using type = typename sequence<TCount - 1,  1, (2 * Ts)...>::type;
};

template<size_t...Ts>
struct sequence<0, Ts...>
{
using type = int_seq<Ts...>;
};

template<size_t TCount>
using create_int_seq  = typename sequence<TCount + 1>::type;

template <typename T>
void print(T val)
{
std::cout << val << " ";
}

template <typename T, typename... Ts>
void print(T val, Ts... t)
{
std::cout << val << " ";
print(t...);
}

template <
template <size_t...> class T,
size_t... S
>
void printing_type(T<S...>)
{
print(S...);
}

int main()
{
constexpr size_t N = 63;
create_int_seq<N> dum{};
printing_type(dum);
}


Certainly your definitions of printing_type and print could be shortened. You're currently doing

print(t...)  // print(a,b,c,d)


but what you actually want to happen is

print(t)...  // print(a), print(b), print(c), print(d)


So then you have to do a bunch of extra work to transform the former into the latter. Instead of all that extra work, you could just write

void print(size_t val) {
std::cout << val << " ";
}

template<template<size_t...> class T, size_t... S>
void printing_type(T<S...>) {
(print(S) , ...);
}


Notice that the single-argument print doesn't have to be a template, because val is always a size_t.

In fact, we can inline print into printing_type if we want:

template<template<size_t...> class TT, size_t... Values>
void printing_type(TT<Values...>) {
((std::cout << Values << " ") , ...);
}


The (ts , ...) syntax is a C++17 fold-expression. If you aren't on C++17, then you can use an initializer list to accomplish the same thing:

template<template<size_t...> class TT, size_t... Values>
void printing_type(TT<Values...>) {
int dummy[] = {
((std::cout << Values << " "), 0) ...
};
}


Your definition for sequence is pretty confusing. Your code could benefit from some unit tests. Compile-time unit tests are easy:

static_assert(std::is_same<create_int_seq<0>, int_seq<1>>::value, "");
static_assert(std::is_same<create_int_seq<1>, int_seq<1,2>>::value, "");
static_assert(std::is_same<create_int_seq<2>, int_seq<1,2,4>>::value, "");
static_assert(std::is_same<create_int_seq<3>, int_seq<1,2,4,8>>::value, "");
static_assert(std::is_same<create_int_seq<4>, int_seq<1,2,4,8,16>>::value, "");


As a bonus, these five lines serve as excellent documentation about what this code does... to the extent that I no longer mind the lack of code comments explaining how it might work.

FWIW, if I wanted to make these test cases pass, I'd implement create_int_seq like this:

template<class> struct powers_of_two;
template<size_t... Is>
struct powers_of_two<std::index_sequence<Is...>> {
using type = int_seq<(size_t(1) << Is)...>;
};

template<size_t N>
using create_int_seq =
typename powers_of_two<std::make_index_sequence<N+1>>::type;


Relevant blog post of mine: "Template metaprogramming: Iteration is better than recursion" (July 2018).

• Man, you blow me away with those changes! Thank you so so much. Still trying to take it in. And yes, I am using c++14 currently for this. Aug 2, 2020 at 16:45
• Hi @Quuxplusone, I need to retain both print() and printing_type meta functions, and since I am using c++14, is there another optimize way instead of using the initializer list method as you have mentioned for c++14, such that I am able to use both print() and printing_type functions at the same time. And, FYI, the compiler has issued a warning being treated as error that the "dummy" variable isn't used. Hope to hear more from you. Thank you. Aug 2, 2020 at 17:26
• Re unused variable dummy: Add (void)dummy; in the body of that function. Re needing to keep some function named print: Add void print() {} :) Aug 3, 2020 at 1:50