遍历模板 int
Iterate over template int
我有一个功能:
template<class Real, int N>
constexpr std::array<Real, N> get_array();
而且我想在很多类型和很多整数上测试它。在伪代码中:
auto types = {float, double, long double};
for(int i = 0; i < 25; ++i) {
for (type : types) {
auto arr = get_array<type, i>();
// test arr
}
}
显然这不能编译。有没有办法修补循环以使其循环,以便我可以遍历数组?
既然你已经 Boost.Hana 标记了,我们就可以使用它了:
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>();
});
});
如下(不加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;
}
接受的答案很好,但如果您不想污染您的调用堆栈,最好在到达实际的 运行 时间之前完成所有可能的处理.
此处的示例使用 hana::cartesian_product
which is probably overkill for ad hoc use cases, but you could use nested hana::unpack
s 来获得相同的效果。
这是一个工作示例:
#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>>));
}
我有一个功能:
template<class Real, int N>
constexpr std::array<Real, N> get_array();
而且我想在很多类型和很多整数上测试它。在伪代码中:
auto types = {float, double, long double};
for(int i = 0; i < 25; ++i) {
for (type : types) {
auto arr = get_array<type, i>();
// test arr
}
}
显然这不能编译。有没有办法修补循环以使其循环,以便我可以遍历数组?
既然你已经 Boost.Hana 标记了,我们就可以使用它了:
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>();
});
});
如下(不加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;
}
接受的答案很好,但如果您不想污染您的调用堆栈,最好在到达实际的 运行 时间之前完成所有可能的处理.
此处的示例使用 hana::cartesian_product
which is probably overkill for ad hoc use cases, but you could use nested hana::unpack
s 来获得相同的效果。
这是一个工作示例:
#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>>));
}