通过模板参数给定其长度,在编译时生成相同类型的 std::tuple
Produce std::tuple of same type in compile time given its length by a template argument
在 C++ 中,如何实现一个带有指示元组长度的 int 模板参数的函数并生成具有该长度的 std::tuple?
例如
func<2>() returns std::tuple<int, int>();
func<5>() returns std::tuple<int, int, int, int, int>().
使用 index_sequence
和辅助类型别名,您可以生成所需的类型:
// Just something to take a size_t and give the type `int`
template <std::size_t>
using Integer = int;
// will get a sequence of Is = 0, 1, ..., N
template <std::size_t... Is>
auto func_impl(std::index_sequence<Is...>) {
// Integer<Is>... becomes one `int` for each element in Is...
return std::tuple<Integer<Is>...>{};
}
template <std::size_t N>
auto func() {
return func_impl(std::make_index_sequence<N>{});
}
值得一提的是,在一般情况下,使用 std::array
可能会更好(在您的情况下,您不能使用一个),但 std::array
可以表现得像一个元组,类似于 std::pair
.
更新:因为你已经明确表示你正在使用 c++11 而不是 14+,你需要从某个地方获得 index_sequence
和相关的实现(here 是 libc++ 的)。这是具有显式 return 类型的 func
和 func_impl
的 C++11 版本:
template <std::size_t... Is>
auto func_impl(std::index_sequence<Is...>) -> std::tuple<Integer<Is>...> {
return std::tuple<Integer<Is>...>{};
}
template <std::size_t N>
auto func() -> decltype(func_impl(std::make_index_sequence<N>{})) {
return func_impl(std::make_index_sequence<N>{});
}
普通的旧递归是你的朋友:
template<std::size_t N>
auto array_tuple() {
return std::tuple_cat(std::tuple<int>{}, array_tuple<N-1>());
}
template<>
auto array_tuple<0>() {
return std::tuple<>{};
}
如果您可以使用 C++14 解决方案, 是您的最佳选择。
使用 C++11,您可以执行以下操作(仍然基于 index_sequence
,但可以在 C++11 中实现):
template <size_t N, class T, class = std::make_index_sequence<N>>
struct n_tuple;
template <size_t N, class T, size_t... Is>
struct n_tuple<N, T, std::index_sequence<Is...>> {
template <size_t >
using ignore = T;
using type = std::tuple<ignore<Is>...>;
};
template <size_t N, class T>
using n_tuple_t = typename n_tuple<N, T>::type;
有了那个:
template <size_t N>
n_tuple_t<N, int> func() {
return n_tuple_t<N, int>{};
}
这是一个带有别名模板的递归解决方案,它可以在 C++11 中实现:
template <size_t I,typename T>
struct tuple_n{
template< typename...Args> using type = typename tuple_n<I-1, T>::template type<T, Args...>;
};
template <typename T>
struct tuple_n<0, T> {
template<typename...Args> using type = std::tuple<Args...>;
};
template <size_t I,typename T> using tuple_of = typename tuple_n<I,T>::template type<>;
例如如果我们想要"tuple of 3 doubles"
我们可以这样写:
tuple_of<3, double> t;
这里有两个 boost.hana 解决方案 (C++14):
//first
hana::replicate<hana::tuple_tag>(int{}, hana::size_c<2>);
//second
hana::cycle(std::make_tuple(int{}), hana::size_c<2>);
两者都生成大小为 2 的整数元组,但它们生成的不是 std::tuple
s,而是 hana::tuple
s。
在 C++ 中,如何实现一个带有指示元组长度的 int 模板参数的函数并生成具有该长度的 std::tuple?
例如
func<2>() returns std::tuple<int, int>();
func<5>() returns std::tuple<int, int, int, int, int>().
使用 index_sequence
和辅助类型别名,您可以生成所需的类型:
// Just something to take a size_t and give the type `int`
template <std::size_t>
using Integer = int;
// will get a sequence of Is = 0, 1, ..., N
template <std::size_t... Is>
auto func_impl(std::index_sequence<Is...>) {
// Integer<Is>... becomes one `int` for each element in Is...
return std::tuple<Integer<Is>...>{};
}
template <std::size_t N>
auto func() {
return func_impl(std::make_index_sequence<N>{});
}
值得一提的是,在一般情况下,使用 std::array
可能会更好(在您的情况下,您不能使用一个),但 std::array
可以表现得像一个元组,类似于 std::pair
.
更新:因为你已经明确表示你正在使用 c++11 而不是 14+,你需要从某个地方获得 index_sequence
和相关的实现(here 是 libc++ 的)。这是具有显式 return 类型的 func
和 func_impl
的 C++11 版本:
template <std::size_t... Is>
auto func_impl(std::index_sequence<Is...>) -> std::tuple<Integer<Is>...> {
return std::tuple<Integer<Is>...>{};
}
template <std::size_t N>
auto func() -> decltype(func_impl(std::make_index_sequence<N>{})) {
return func_impl(std::make_index_sequence<N>{});
}
普通的旧递归是你的朋友:
template<std::size_t N>
auto array_tuple() {
return std::tuple_cat(std::tuple<int>{}, array_tuple<N-1>());
}
template<>
auto array_tuple<0>() {
return std::tuple<>{};
}
如果您可以使用 C++14 解决方案,
使用 C++11,您可以执行以下操作(仍然基于 index_sequence
,但可以在 C++11 中实现):
template <size_t N, class T, class = std::make_index_sequence<N>>
struct n_tuple;
template <size_t N, class T, size_t... Is>
struct n_tuple<N, T, std::index_sequence<Is...>> {
template <size_t >
using ignore = T;
using type = std::tuple<ignore<Is>...>;
};
template <size_t N, class T>
using n_tuple_t = typename n_tuple<N, T>::type;
有了那个:
template <size_t N>
n_tuple_t<N, int> func() {
return n_tuple_t<N, int>{};
}
这是一个带有别名模板的递归解决方案,它可以在 C++11 中实现:
template <size_t I,typename T>
struct tuple_n{
template< typename...Args> using type = typename tuple_n<I-1, T>::template type<T, Args...>;
};
template <typename T>
struct tuple_n<0, T> {
template<typename...Args> using type = std::tuple<Args...>;
};
template <size_t I,typename T> using tuple_of = typename tuple_n<I,T>::template type<>;
例如如果我们想要"tuple of 3 doubles"
我们可以这样写:
tuple_of<3, double> t;
这里有两个 boost.hana 解决方案 (C++14):
//first
hana::replicate<hana::tuple_tag>(int{}, hana::size_c<2>);
//second
hana::cycle(std::make_tuple(int{}), hana::size_c<2>);
两者都生成大小为 2 的整数元组,但它们生成的不是 std::tuple
s,而是 hana::tuple
s。