Reputation: 5161
I have a function:
template<class Real, int N>
constexpr std::array<Real, N> get_array();
and I would like to test it over many types and many integers. In pseudocode:
auto types = {float, double, long double};
for(int i = 0; i < 25; ++i) {
for (type : types) {
auto arr = get_array<type, i>();
// test arr
}
}
Obviously this doesn't compile. Is there a way to patch up the loop to make it so I can iterate over the array?
Upvotes: 2
Views: 194
Reputation: 1696
The accepted answer is good, but if you don't want to pollute your call stack, it is better to do all of the processing that you can before you get to the actual run-time stuff.
The example here is using hana::cartesian_product
which is probably overkill for ad hoc use cases, but you could use nested hana::unpack
s to get the same effect.
Here is a working example:
#include <array>
#include <boost/hana/assert.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/cartesian_product.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/transform.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
template <typename Real, int N>
constexpr std::array<Real, N> get_array() {
return {};
}
int main() {
auto types = hana::tuple_t<float, double, long, double>;
auto lengths = hana::to_tuple(hana::range_c<int, 0, 4>);
auto tls = hana::cartesian_product(hana::make_tuple(types, lengths));
auto get_array_fns = hana::transform(tls, [](auto pair) {
return [] {
return get_array<typename decltype(+hana::at_c<0>(pair))::type,
decltype(+hana::at_c<1>(pair))::value>();
};
});
hana::for_each(get_array_fns, [](auto get_array) {
auto arr = get_array();
// test arr
});
auto result_types = hana::unpack(get_array_fns, [](auto ...get_array) {
return hana::tuple_t<decltype(get_array())...>;
});
BOOST_HANA_CONSTANT_CHECK(hana::equal(
decltype(result_types){},
hana::tuple_t<std::array<float, 0>,
std::array<float, 1>,
std::array<float, 2>,
std::array<float, 3>,
std::array<double, 0>,
std::array<double, 1>,
std::array<double, 2>,
std::array<double, 3>,
std::array<long, 0>,
std::array<long, 1>,
std::array<long, 2>,
std::array<long, 3>,
std::array<double, 0>,
std::array<double, 1>,
std::array<double, 2>,
std::array<double, 3>>));
}
Upvotes: 2
Reputation: 302852
Since you have Boost.Hana tagged anyway, we can just use it:
auto types = hana::tuple_t<float, double, long double>;
hana::for_each(types, [](auto type){
hana::for_each(std::make_index_sequence<25>(), [=](auto idx){
// here type is an object that denotes the type and
// idx is an integral constant that denotes the next value
get_array<typename decltype(type)::type, idx>();
});
});
Upvotes: 2
Reputation: 66200
What about as follows (without boost)?
#include <array>
#include <iostream>
template <typename T, std::size_t Dim>
constexpr std::array<T, Dim> get_array ()
{ return {}; }
// fake test
template <typename T, std::size_t Dim>
constexpr bool checkArray (std::array<T, Dim> const &)
{ return true; }
template <typename T, std::size_t ... Is>
constexpr bool checkSequence (std::index_sequence<Is...> const &)
{ return (... && checkArray(get_array<T, Is>())); }
template <typename ... Ts>
constexpr bool checkTypes ()
{ return (... && checkSequence<Ts>(std::make_index_sequence<25u>{})); }
int main ()
{
constexpr auto value = checkTypes<float, double, long double>();
std::cout << value << std::endl;
}
Upvotes: 1