Consider the following code:
template <class Scalar, class Array, class Tuple>
class Test {};
where Array
is a std::array
, and Tuple
is a std::tuple
. In this class, I will have a lot of SFINAE, and I would like to create a big tuple called Types
that will contain the complete list of types. This will allow me to test some conditions with variadic lists.
So the challenge is to create a type that will have the following behaviour. If:
Scalar = int
Array = std::array<double, 3>
Tuple = std::tuple<char, float, std::string>
Then:
Types = std::tuple<int, double, double, double, char, float, std::string>
which is the concatenation of the internal data of the Scalar
, Array
and Tuple
.
How to do that ?
This seems to work:
template<typename T1, typename T2>
struct concat_tuples;
template<typename... T1, typename... T2>
struct concat_tuples<std::tuple<T1...>, std::tuple<T2...>>
{
using type = std::tuple<T1..., T2...>;
};
// n_tuple<int, 3>::type == std::tuple<int, int, int>
template<typename T, size_t n>
struct n_tuple;
template<typename T>
struct n_tuple<T, 0>
{
using type = std::tuple<>;
};
template<typename T, size_t n>
struct n_tuple
{
using type = typename concat_tuples<
typename n_tuple<T, n-1>::type,
std::tuple<T>
>::type;
};
template <class Scalar, class Array, class Tuple>
struct Test;
template <class Scalar, typename T, size_t n, typename... Ts>
struct Test<Scalar, std::array<T, n>, std::tuple<Ts...>>
{
using type = typename concat_tuples<
typename concat_tuples<
std::tuple<Scalar>,
typename n_tuple<T, n>::type
>::type,
std::tuple<Ts...>
>::type;
};
Live demo here .
Use a partial specialization to deduce the types, and Xeo's tuple_cat
comment to put them together ( Live at Coliru :
template <typename ArrayType, std::size_t ArraySize, typename... Fields>
struct ArrayTuple : ArrayTuple<ArrayType, ArraySize-1, ArrayType, Fields...> {};
template <typename ArrayType, typename... Fields>
struct ArrayTuple<ArrayType, 0, Fields...> {
using type = std::tuple<Fields...>;
};
template <typename, typename, typename> class Test;
template <typename Scalar, typename ArrayType, std::size_t ArraySize, typename... Fields>
class Test<Scalar, std::array<ArrayType, ArraySize>, std::tuple<Fields...>> {
public:
// Modified tuple_cat code from Xeo's comment:
using Tuple = std::tuple<Fields...>;
using Types = decltype(
std::tuple_cat(std::tuple<Scalar>(),
typename ArrayTuple<ArrayType, ArraySize>::type(),
std::declval<Tuple>()));
};
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.