如何获取给定元组类型中第一个元素的元组类型?
如果我只要求一个元素,它应该给我内部类型而不是一个元素的元组类型。
在代码中,我如何获得type
我正在寻找?
//TupleType is a tuple of n types 0,1,2,...,n-1
template<size_t i, typename TupleType>
struct first_elements {
using type = //the "sub-tuple" of types 0,1,2,...,i
//exception: if i=0, just the bare type within
//the tuple, not the tuple of one element
};
完成后,我可以像这样使用它:
using my_tuple_type = first_elements<1,decltype(great_tuple)>::type;
using not_tuple_type = first_elements<0,decltype(great_tuple)>::type;
答案 0 :(得分:2)
我几乎没有测试,但想法应该没问题:
很长但很直接
#include <tuple>
#include <iostream>
template<int n, typename In, typename... Out>
struct first_impl;
template<int n, typename First, typename... Other, typename... Out>
struct first_impl<n, std::tuple<First, Other...>, Out...> {
typedef typename first_impl<n - 1, std::tuple<Other...>, Out..., First>::type type; //move first input to output.
};
//need First, Other... here to resolve ambiguity on n = 0
template<typename First, typename... Other, typename... Out>
struct first_impl<0, std::tuple<First, Other...>, Out...> {
typedef typename std::tuple<Out...> type; //stop if no more elements needed
};
//explicit rule for empty tuple because of First, Other... in the previous rule.
// actually it's for n = size of tuple
template<typename... Out>
struct first_impl<0, std::tuple<>, Out...> {
typedef typename std::tuple<Out...> type;
};
//Simple check
int main() {
typedef first_impl<2, std::tuple<char, long, int>>::type type;
std::cout << std::is_same<type, std::tuple<char, long>>::value; // 1
return 0;
}
之后你需要使异常工作:
template<int n, typename T>
class first_elements<n, T> {
typedef typename first_impl<n, T>:: type type;
}
template<typename First, typename... Other>
class first_elements<0, std::tuple<First, Other...>> {
typedef First type;
}
template<>
class first_elements<0, std::tuple<>>; // make it incomplete
答案 1 :(得分:1)
std::tuple_element<0, TupleType>::type
与标准索引包技术一起使用,您也可以使用它来创建子数,例如std::tuple<typename std::tuple_element<Indices, TupleType>::type...>
。
答案 2 :(得分:1)
<强>更新强>
如果您在这里寻找将提取指定的代码
给定std::tuple
的子序列和/或定义子序列的类型
给定的std::tuple
- 类型,跳到 Anwser到明显的问题。
OP的问题实际上不是那个问题。
回答实际问题
这样做:
#include <cstddef>
#include <type_traits>
#include <tuple>
template<size_t I, typename TupleType, typename Enable = void>
struct first_elements;
template<size_t I, typename TupleType>
struct first_elements<I,TupleType,typename std::enable_if<(I == 0)>::type>
{
using type = typename std::tuple_element<0,TupleType>::type;
};
template<size_t I, typename TupleType>
struct first_elements<I,TupleType,typename std::enable_if<(I == 1)>::type>
{
using type =
typename std::tuple<typename std::tuple_element<0,TupleType>::type>;
};
template<size_t I, typename TupleType>
struct first_elements<I,TupleType,typename std::enable_if<(I > 1)>::type>
{
using next =
typename std::tuple<typename std::tuple_element<I - 1,TupleType>::type>;
using prev = typename first_elements<I - 1,TupleType>::type;
using type = decltype(
std::tuple_cat(std::declval<prev>(),std::declval<next>())
);
};
// A test program...
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
auto tup = std::tuple<char,int,float,double>();
cout <<
std::is_same<first_elements<0,decltype(tup)>::type,char>::value << endl;
cout <<
std::is_same<first_elements<1,decltype(tup)>::type,std::tuple<char>>::value
<< endl;
cout <<
std::is_same<
first_elements<2,decltype(tup)>::type,
std::tuple<char,int>>::value
<< endl;
cout <<
std::is_same<
first_elements<3,decltype(tup)>::type,
std::tuple<char,int,float>>::value
<< endl;
cout <<
std::is_same<
first_elements<4,decltype(tup)>::type,
std::tuple<char,int,float,double>>::value
<< endl;
return 0;
}
编译时范围错误没有特别的预防措施。他们将barf as
std::tuple
让他们成为barf。
(gcc 4.7.2 / 4.8.1.clang 3.3,-std=c++11
)
回答明显的问题
#include <type_traits>
#include <tuple>
/* A class template to obtain the type and value of the
the subsequence [First,Last) of a tuple type TupleType
First:- The start of the subsequence [First,Last)
Last:- The end of the subsequence [First,Last)
TupleType: - The std::tuple type to be queried.
Enable:- SFINAE parameter
The public member `type` is defined as the type of the
subsequence [First,Last) of `TupleType`.
The static member function:
`type get(TupleType const & tup)`
returns the `std::tuple` of the subsequence [First,Last) of `tup`.
`std::tuple<>` is returned when `First`
is out of range. The terminal sub-tuple indexed by `First` is
returned if only `Last` is out of range.
*/
template<
unsigned First, unsigned Last, typename TupleType, typename Enable = void
>
struct tuple_part;
template<unsigned First, unsigned Last, typename TupleType>
struct tuple_part<
First,Last,TupleType,
typename std::enable_if<
(First >= Last || First >= std::tuple_size<TupleType>::value)
>::type
>
{
using type = std::tuple<>;
static constexpr type get(TupleType const & tup) {
return type();
}
};
template<unsigned First, unsigned Last, typename TupleType>
struct tuple_part<
First,Last,TupleType,
typename std::enable_if<
(Last == First + 1 && First < std::tuple_size<TupleType>::value)
>::type
>
{
using type =
typename std::tuple<typename std::tuple_element<First,TupleType>::type>;
static constexpr type get(TupleType const & tup) {
return type(std::get<First>(tup));
}
};
template<unsigned First, unsigned Last, typename TupleType>
struct tuple_part<
First,Last,TupleType,
typename std::enable_if<
(Last > First + 1 && Last <= std::tuple_size<TupleType>::value)
>::type
>
{
using head = typename tuple_part<First,First + 1,TupleType>::type;
using tail = typename tuple_part<First + 1,Last,TupleType>::type;
using type = decltype(
std::tuple_cat(std::declval<head>(),std::declval<tail>())
);
static constexpr type get(TupleType const & tup) {
return std::tuple_cat(
tuple_part<First,First + 1,TupleType>::get(tup),
tuple_part<First + 1,Last,TupleType>::get(tup)
);
}
};
template<unsigned First, unsigned Last, typename TupleType>
struct tuple_part<
First,Last,TupleType,
typename std::enable_if<
(Last > First + 1 && Last > std::tuple_size<TupleType>::value)
>::type
> : tuple_part<First,std::tuple_size<TupleType>::value,TupleType>
{
using base_type =
tuple_part<First,std::tuple_size<TupleType>::value,TupleType>;
using type = typename base_type::type;
};
/*
`get_part<First,Last>(TupleType const & tup)`
returns the `std::tuple` of the subsequence [First,Last) of `tup`
*/
template<unsigned First, unsigned Last, typename TupleType>
constexpr
decltype(
tuple_part<First,Last,TupleType>::get(std::declval<TupleType>())
)
get_part(TupleType const & tup)
{
return tuple_part<First,Last,TupleType>::get(tup);
}
/*
`get_part<First>(TupleType const & tup)`
returns the `std::tuple` of the terminal subsequence of `tup`
indexed by `First`
*/
template<unsigned First, typename TupleType>
constexpr
decltype(
get_part<First,std::tuple_size<TupleType>::value>(std::declval<TupleType>())
)
get_part(TupleType const & tup)
{
return get_part<First,std::tuple_size<TupleType>::value>(tup);
}
// A test program...
#include <cassert>
int main(int argc, char **argv)
{
using type = std::tuple<char,int,float,double>;
constexpr type t0(1,2,3.0,4.0);
constexpr auto p0 = get_part<0,1>(t0);
assert(p0 == std::tuple<char>(1));
auto p1 = get_part<0,2>(t0);
assert((p1 == std::tuple<char,int>(1,2)));
auto p2 = get_part<0,3>(t0);
assert((p2 == std::tuple<char,int,float>(1,2,3.0)));
auto p3 = get_part<0>(t0);
assert((p3 == std::tuple<char,int,float,double>(1,2,3.0,4.0)));
auto p4 = get_part<1,2>(t0);
assert(p4 == std::tuple<int>(2));
auto p5 = get_part<1,3>(t0);
assert((p5 == std::tuple<int,float>(2,3.0)));
auto p6 = get_part<1>(t0);
assert((p6 == std::tuple<int,float,double>(2,3.0,4.0)));
auto p7 = get_part<2,3>(t0);
assert(p7 == std::tuple<float>(3.0));
auto p8 = get_part<2,4>(t0);
assert((p8 == std::tuple<float,double>(3.0,4.0)));
auto p9 = get_part<3>(t0);
assert(p9 == std::tuple<double>(4.0));
auto p10 = get_part<3,5>(t0);
assert(p10 == std::tuple<double>(4.0));
auto p11 = get_part<4,4>(t0);
assert(p11 == std::tuple<>());
auto p12 = get_part<5,4>(t0);
assert(p12 == std::tuple<>());
return 0;
}
// EOF
(gcc 4.7.2 / 4.8.1,clang 3.2 / 3.3,-std=c++11
)