I wanted to define a variadic tuple type to represent coordinates. For example, for some magic type:
template <unsigned int N>
struct CoordT {
typedef std::tuple<_some_magic_> coord_type;
};
I'd like to have CoordT<3>::coord_type
to be the 3-dimensional coordinate type:
std::tuple<double, double, double>
.
But I don't know how to use template programming to generate N
repeated double
s.
Can anyone please help explain how to write it?
Use std::make_integer_sequence
to generate a pack of the appropriate length, then map the elements to doubles:
template <size_t n>
struct TupleOfDoubles {
template <size_t... i>
static auto foo(std::index_sequence<i...>) {
return std::make_tuple(double(i)...);
}
using type = decltype(foo(std::make_index_sequence<n>{}));
};
If you don't literally need a std::tuple
, but just need something which acts like a tuple, use std::array
:
template <unsigned int N>
struct CoordT {
typedef std::array<double, N> coord_type;
};
std::array
has overloads for std::get<I>
, std::tuple_size
, and std::tuple_element
. Most library and language facilities which accept a tuple-like element will support std::array
, such as std::apply
and structured bindings .
Is too late to play?
If for you is acceptable to declare (no definition is needed) a variadic template function as follows
template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
-> decltype(a);
and that the coord_type
is defined in a CoordT
specialization, you can write it as follows
template <std::size_t N,
typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;
template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
{ using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };
The following is a full C++14 compiling example
#include <tuple>
#include <type_traits>
template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
-> decltype(a);
template <std::size_t N,
typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;
template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
{ using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };
int main()
{
using t0 = std::tuple<double, double, double, double>;
using t1 = typename CoordT<4u>::coord_type;
static_assert( std::is_same<t0, t1>::value, "!" );
}
A very concise way to do this is by using std::tuple_cat
and std::array
:
template <unsigned int N>
struct CoordT {
using coord_type = decltype(std::tuple_cat(std::array<double, N>{}));
};
std::tuple_cat
is allowed to support tuple-like types such as std::array
, but not guaranteed. However, every implementation I checked supports this .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.