如何获取元组的一部分? [英] How to obtain a part of a tuple?
问题描述
如何获取给定元组类型中第一个元素的元组类型?
如果我只需要一个元素,它应该给我内部类型而不是一个元素类型的一个元素。
在代码中,我将如何获得类型
for?
// TupleType是n类型0,1,2,...,n-1 $ b的元组$ b template< size_t i,typename TupleType>
struct first_elements {
使用type = //类型0,1,2,...,i
的子元组//异常:如果i = 0,
中的裸类型//元组,而不是一个元素的元组
};
完成后,我可以这样使用:
使用my_tuple_type = first_elements< 1,decltype(great_tuple)> :: type;
使用not_tuple_type = first_elements< 0,decltype(great_tuple)> :: type;
UPDATE >
如果你在这里寻找代码,将提取指定的
子序列给定的 std :: tuple
和/或定义给定 std :: tuple -type 的子序列
的类型,跳到 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> ;;
};
模板< 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>())
);
};
//测试程序...
#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 < 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作为
std :: tuple
使他们barf。
(gcc 4.7.2 / 4.8.1.clang 3.3, -std = c ++ 11
)
#include< type_traits>
#include< tuple>
/ *类模板获取
的类型和值元组类型的子序列[First,Last)TupleType
首先: - 开始的子序列[First,Last)
Last: - 子序列的结束[First,Last)
TupleType: - 要查询的std :: tuple类型。
启用: - SFINAE参数
公共成员`type`被定义为`TupleType`的
子序列[First,Last]的类型。
静态成员函数:
`type get(TupleType const& tup)`
返回`std :: tuple` `tup`的子序列[First,Last]。
`````$`$ b`b`std :: tuple<>`在`First`
超出范围时返回。如果只有Last超出范围,则由First索引的终端子元组返回
。
* /
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&&< = 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& ,
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<
(最后>第一个+ 1&&&&&> 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)`
返回子序列[First,Last]的`std :: tuple `tup`
* /
template< unsigned First,unsigned Last,typename TupleType>
constexpr
decltype(
tuple_part< First,Last,TupleType> :: get(std :: declval< TupleType>())
)
get_part & tup)
{
return tuple_part< First,Last,TupleType> :: get(tup);
}
/ *
`get_part< First>(TupleType const& tup)`
返回`std :: tuple' tup`
由`First`索引
* /
模板< 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);
}
//测试程序...
#include< cassert>
int main(int argc,char ** argv)
{
使用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
/4.8.1,clang 3.2 / 3.3, -std = c ++ 11
)
How can I obtain the tuple type of the first elements in a given tuple type?
If I only ask for one element, it should give me the inner type instead of a tuple type of one element.
In code, how would I get the type
I'm looking for?
//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
};
Once finished, I could use it like this:
using my_tuple_type = first_elements<1,decltype(great_tuple)>::type;
using not_tuple_type = first_elements<0,decltype(great_tuple)>::type;
UPDATE
If you have got here seeking code that will extract a specified
subsequence of a given std::tuple
and/or define the type of a subsequence
of a given std::tuple
-type, skip to Anwser to the apparent question.
The OP's question is actually not that one.
Answer to the actual question
This will do:
#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;
}
No special precautions for compiletime range-errors. They will barf as
std::tuple
makes them barf.
(gcc 4.7.2/4.8.1.clang 3.3, -std=c++11
)
Anwser to the apparent question
#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
)
这篇关于如何获取元组的一部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!