Confused with a simple mix of templates and non-type functions that return a tuple
As an exercise, I am trying to write 2 simple functions that take the non-type int N pattern. First, I need to create a tuple of N copies of some object of type T. I would like it to resemble the following:
template <class T, int N>
constexpr std::tuple<T...> fun(T t) {
return (N > 0) ? std::tuple_cat(t, fun<T, N-1>(t)) : std::make_tuple(t);
}
I have also tried something like this without success ( http://liveworkspace.org/code/3LZ0Fe ). I would like to be able to create an instance with T = bool, say:
auto bools = fun<bool, 10> (false);
The second should be a small change; I have a templated structure Foo and I would like to create a tuple containing Foo <0>, ..., Foo <N>
template <int N> struct Foo {
static const int id = N;
}
template <template <int> class T, int N>
constexpr ??? fun2 (???) {...}
Since templated functions cannot be partially specialized, I don't even know how to write the correct completion for my recursion. I would like to do this completely statically, without using for loops.
=============================================== === ================================
Following Seth's suggestion, I got stuck writing the fun function itself, which repeated endlessly:
template<typename T, int N>
typename fun_helper<T, N>::type
fun(T t) {
if (N > 0)
return typename fun_helper<T, N>::type
{ std::tuple_cat(std::make_tuple(t), fun<T, N-1>(t)) };
else return typename fun_helper<T, N>::type { };
}
Using an additional structure with completion, I was able to get this working:
template<typename T, int N> struct fun {
typename fun_helper<T, N>::type make(T t) {
return typename fun_helper<T, N>::type
{ std::tuple_cat(std::make_tuple(t), fun<T, N-1>().make(t)) };
}
};
template<typename T> struct fun<T, 0> {
typename fun_helper<T, 0>::type
make(T t) {
return typename fun_helper<T, 0>::type { };
}
};
The call is still relatively clunky:
auto conds = fun<bool, 3>().make(false);
Is there a way to make it work without this extra structure?
auto conds = fun<bool, 3>(false);
source to share
First, you can recursively construct a parameter pack using struct
for partial specialization (I show you this path because it belongs to # 2). This code is untested and doesn't care about the default value for elements, but it does give you an idea and the default value code can be easily added.
template<typename T, int N, typename... Rest>
struct fun_helper {
typedef typename fun_helper<T, N - 1, T, Rest...>::type type;
};
template<typename T, typename... Rest>
struct fun_helper<T, 0, Rest...> {
typedef std::tuple<Rest...> type;
};
template<typename T, int N>
typename fun_helper<T, N>::type fun() {
return typename fun_helper<T, N>::type { };
}
In the second case, you can combine the above methods with a parameter package int
and use ...
to extend them, for example
Foo<Ints>...
which expands to
Foo<Int1>, Foo<Int2>, ...
in your function.
source to share