Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何获取元组的一部分?_C++_Templates_C++11_Tuples - Fatal编程技术网

C++ 如何获取元组的一部分?

C++ 如何获取元组的一部分?,c++,templates,c++11,tuples,C++,Templates,C++11,Tuples,如何获取给定元组类型中第一个元素的元组类型 如果我只要求一个元素,它应该给我内部类型,而不是一个元素的元组类型 在代码中,我如何获得我要查找的类型 //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

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

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

在代码中,我如何获得我要查找的
类型

//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
};
//TupleType是一个包含n种类型0,1,2,…,n-1的元组
模板
结构优先元素{
使用type=//类型0,1,2,…,i的“子元组”
//例外情况:如果i=0,则仅为
//元组,而不是一个元素的元组
};
完成后,我可以这样使用它:

using my_tuple_type = first_elements<1,decltype(great_tuple)>::type;
using not_tuple_type = first_elements<0,decltype(great_tuple)>::type;
使用我的元组类型=第一个元素::类型;
使用非元组类型=第一个元素::类型;
使用:

std::tuple\u元素::类型
与标准索引包技术一起,您还可以使用它来创建子元组,如
std::tuple

使用:

std::tuple\u元素::类型

与标准索引包技术一起,您还可以使用它来创建子元组,如
std::tuple

我几乎没有测试过,但idea应该可以:

很长但很直接

#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;
}
#包括
#包括
模板
结构优先;
模板
结构优先执行{
typedef typename first\u impl::type type;//将第一个输入移动到输出。
};
//需要首先,其他。。。此处用于解决n=0上的歧义
模板
结构优先执行{
typedef typename std::tuple type;//如果不需要更多元素,则停止
};
//空元组的显式规则,因为第一个、其他。。。在上一条规则中。
//实际上,这是n=元组的大小
模板
结构优先执行{
typedef typename std::元组类型;
};
//简单检查
int main(){
typedef first_impl::type type;

std::cout我几乎并没有测试,但想法应该可以:

很长但很直接

#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;
}
#包括
#包括
模板
结构优先;
模板
结构优先执行{
typedef typename first\u impl::type type;//将第一个输入移动到输出。
};
//需要首先,其他…在这里解决n=0的歧义
模板
结构优先执行{
typedef typename std::tuple type;//如果不需要更多元素,则停止
};
//由于前一个规则中的第一个、其他…而导致空元组的显式规则。
//实际上,这是n=元组的大小
模板
结构优先执行{
typedef typename std::元组类型;
};
//简单检查
int main(){
typedef first_impl::type type;

标准::cout更新

如果您在这里查找将提取指定 给定
std::tuple
的子序列和/或定义子序列的类型 对于给定的
std::tuple
-类型,跳到并转到明显的问题。 OP的问题其实不是那个

对实际问题的回答

#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
这将有助于:

#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;
}

(gcc 4.7.2/4.8.1,clang 3.2/3.3,
-std=c++11

更新

如果您在这里查找将提取指定 给定
std::tuple
的子序列和/或定义子序列的类型 对于给定的
std::tuple
-类型,跳到并转到明显的问题。 OP的问题其实不是那个

对实际问题的回答

#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
这将有助于:

#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;
}

(gcc 4.7.2/4.8.1,clang 3.2/3.3,
-std=c++11

您确定这是对
declval
的有效使用吗?您是否使用
tuple\u cat
构造了有效的
tuple
对象,即使
declval
不允许这样做?(然后您获取该对象的
decltype
)@罗杰·詹姆斯,
decltype
的参数是一个未赋值的上下文。因此,我要询问未赋值表达式的类型
std::tuple_cat(std::declval(),std::declval())
,它是“某些给定的
prev
(std::declval())
和“某些给定的
下一个
”的
类型。我不能保证
prev
next
是默认可构造的,所以我
declval
它们。在
decltype(…)
中没有构造任何内容,但是
prev()
next()
甚至不一定会编译。因此
declval
的目的是创建“伪对象”这永远不会成为实际对象?这基本上是正确的。您只能在未计算的上下文中“调用”
declval()
,并“调用”它只是返回一个对
T
的右值引用。您确定这是
declval
的有效使用吗?您是否没有用
tuple\u cat
构造一个有效的
tuple
对象,即使
declval
不允许这样做?(然后您获取该对象的
decltype
)@罗杰·詹姆斯,
decltype
的参数是一个未赋值的上下文。因此,我要询问未赋值表达式的类型
std::tuple_cat(std::declval(),std::declval())
,它是“某些给定的
prev
(std::declval())
和“某些给定的
下一个
”的
类型。我不能保证
prev
next
是默认可构造的,所以我
declval
它们。在
decltype(…)
中没有构造任何内容,但是
prev()
next()
甚至不一定会编译。因此
declval
的目的是创建“伪对象”这永远不会成为实际对象?这基本上是正确的。您只能在未计算的上下文中“调用”
declval()
,而“调用”它只是返回对
T
的右值引用。