如何获取元组的一部分? [英] How to obtain a part of a tuple?

查看:164
本文介绍了如何获取元组的一部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取给定元组类型中第一个元素的元组类型?



如果我只需要一个元素,它应该给我内部类型而不是一个元素类型的一个元素。



在代码中,我将如何获得类型 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆