首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对于std::tuple,如何按类型获取数据,以及如何按索引获取数据?

对于std::tuple,如何按类型获取数据,以及如何按索引获取数据?
EN

Stack Overflow用户
提问于 2013-05-16 17:40:35
回答 2查看 6.5K关注 0票数 5

标题上写着:给定一个std::tuple,我想

  1. 获取给定类型的第一个元素
  2. 获取i-th元素的类型。

是否有STL提供的解决方案?还是解决方案?有人能试着完成我的代码吗?

代码语言:javascript
运行
复制
#include <tuple>

int main ()
{
    std::tuple<int,char,int> mytuple (10,'a', 5);

    // how to get the first int element here? (10)
    // int x = std::get_me_the_first<int>(mytuple);

    // how to get the type of the second element here?
    // std::get_me_type_of<1> ch = 'x';

    return 0;
}

编撰如下:

代码语言:javascript
运行
复制
g++ -std=c++11 -Wall main.cpp -o main
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-16 17:50:33

按类型从元组中获取值(而不是索引)

在C++11中,没有获得T类型元组的第一个元素的STL方法。

在C++14中,应该有一种方法使用新的过载的std::get来做您想做的事情。国际标准化组织的文件位于这里N3404和这里N3670

您可以使用以下方法在C++11中完成此操作:

代码语言:javascript
运行
复制
#include<tuple>
#include<type_traits>
#include<string>
#include<iostream>

template<int Index, class Search, class First, class... Types>
struct get_internal
{
    typedef typename get_internal<Index + 1, Search, Types...>::type type;
        static constexpr int index = Index;
};

template<int Index, class Search, class... Types>
struct get_internal<Index, Search, Search, Types...>
{
    typedef get_internal type;
    static constexpr int index = Index;
};

template<class T, class... Types>
T get(std::tuple<Types...> tuple)
{
    return std::get<get_internal<0,T,Types...>::type::index>(tuple);
}

我把它托管在Ideone 这里上,但是下面是我对后代的测试功能

代码语言:javascript
运行
复制
int main()
{
    std::tuple<int, double, std::string> test{1, 1.7, "test"};
    std::cout<<"get<0> == get<int> :"<< (std::get<0>(test) == get<int>(test))<< "\n";
    std::cout<<"get<1> == get<double> :"<<(std::get<1>(test) == get<double>(test))<< "\n";
    std::cout<<"get<2> == get<std::string> :"<<(std::get<2>(test) == get<std::string>(test))<< "\n";
}

基于@Yakk将其扩展为支持一个类型的多个实例以及要在元组中测试的谓词的想法,他提供了以下代码(也托管在Ideone 这里上)

请注意:在中,std::get的新重载不允许元组中具有相同类型的多个实例。相反,它会发出编译错误。此外,C++14版本也不支持谓词。

代码语言:javascript
运行
复制
//Include same headers as before
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b,T>::type;

template<int Index, template<typename T>class Search, int Which, typename, class First, class... Types>
struct get_internal:
    get_internal<Index + 1, Search, Which, void, Types...>
{};

template<int Index, template<typename T>class Search, int Which, class First, class... Types>
struct get_internal<Index, Search, Which, EnableIf<!Search<First>::value>, First, Types...>:
    get_internal<Index + 1, Search, Which, void, Types...>
{};
template<int Index, template<typename T>class Search, int Which, class First, class... Types>
struct get_internal<Index, Search, Which, EnableIf<Search<First>::value>, First, Types...>:
    get_internal<Index + 1, Search, Which-1, void, Types...>
{};
template<int Index, template<typename T>class Search, class First, class... Types>
struct get_internal<Index, Search, 0, EnableIf<Search<First>::value>, First, Types...>:
    std::integral_constant<int, Index>
{};

template<template<typename>class Test, int Which=0, class... Types>
auto get(std::tuple<Types...>& tuple)->
  decltype(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple))
{
    return std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple);
}
template<template<typename>class Test, int Which=0, class... Types>
auto get(std::tuple<Types...> const& tuple)->
  decltype(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple))
{
    return std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple);
}
template<template<typename>class Test, int Which=0, class... Types>
auto get(std::tuple<Types...>&& tuple)->
  decltype(std::move(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple)))
{
    return std::move(std::get<get_internal<0,Test,Which,void,Types...>::value>(tuple));
}

template<typename T>
struct is_type {
  template<typename U>
  using test = std::is_same<T,U>;
};

template<class T, int Which=0, class... Types>
T& get(std::tuple<Types...>& tuple)
{
    return get<is_type<T>::template test,Which>(tuple);
}
template<class T, int Which=0, class... Types>
T const& get(std::tuple<Types...> const& tuple)
{
    return get<is_type<T>::template test,Which>(tuple);
}
template<class T, int Which=0, class... Types>
T&& get(std::tuple<Types...>&& tuple)
{
    return std::move(get<is_type<T>::template test,Which>(tuple));
}

元组中n-元素的类型

有一种方法可以得到n元素的类型.std::tuple_element<n, decltype(tuple)>::type (感谢@syam)是元组的第n个元素的类型。

票数 10
EN

Stack Overflow用户

发布于 2013-05-16 19:41:37

对于咯咯笑,def不是您想要的,在某种意义上是非常有限的,您必须添加新的类型,并且它可以反向工作,但是这里是getNthTypeReverse,它只支持'int‘和'char’类型haha http://ideone.com/Uk2JTC

代码语言:javascript
运行
复制
#include <tuple>
#include <iostream>
using namespace std;

typedef std::tuple<int,char,int> TupleType;

template<typename TupleT,typename OnElementHandler, size_t N>
struct TupleIterator{    
    static void call(const TupleT& tuple, OnElementHandler& OnElement){ 
        auto nthElem = std::get<N>(tuple);
        OnElement(nthElem);        
        TupleIterator<TupleT,OnElementHandler,N-1>::call(tuple,OnElement);
    }
};
template<typename TupleT,typename OnElementHandler>
struct TupleIterator<TupleT,OnElementHandler,0>{  
     static void call(const TupleT& tuple, OnElementHandler& OnElement){ 
        auto firstElem = std::get<0>(tuple);        
        OnElement(firstElem);
    }
};
template<typename T1,typename T2>
struct IsSame{enum{result = 0};};

template<typename T>
struct IsSame<T,T>{ enum{result = 1}; };

template<typename T,size_t TargetCount, size_t BeginIndex, size_t EndIndex, typename Tuple>
T getNthTypeReverse(const Tuple& t, const T& defaultValue = T()){
    //assert 0 <= N <= tuple.size
    T result = defaultValue;    
    struct NthGrabber{
       T& result;
       const size_t n;
       size_t count;
       NthGrabber(T& r, const size_t n): result(r),n(n),count(0){}
       void operator()(const int i){
           if(IsSame<T,int>::result){
               ++count;
               if(count == n) result = i;
           }

       }
       void operator()(const char c){
           if(IsSame<T,char>::result){
               ++count;
               if(count == n) result = c;
           }
       }
       //overload for other version too...
    }OnElement(result,TargetCount+1); //WILL update result if condition meet
    const size_t tupleSize = EndIndex - BeginIndex;
    TupleIterator<TupleType,NthGrabber,tupleSize>::call(t,OnElement); 
    return result;
}
int main(){
    TupleType t(10,'a',5);    
    const size_t tupleSize = std::tuple_size<decltype(t)>::value - 1;
    int lastInt = getNthTypeReverse<int,0,0,tupleSize,TupleType>(t,-1); 
    int secondLastInt = getNthTypeReverse<int,1,0,tupleSize,TupleType>(t,-1); 
    int thirdLastInt = getNthTypeReverse<int,2,0,tupleSize,TupleType>(t,-1); 
    cout << "lastInt = " << lastInt << endl;    
    cout << "SecondLast = " << secondLastInt << endl;
    cout << "ThirdLast = " << thirdLastInt << endl;

    char lastChar = getNthTypeReverse<char,0,0,tupleSize,TupleType>(t,'\0'); 
    cout << "LastChar = "  << lastChar << endl;

    return 0;
}

产出:

代码语言:javascript
运行
复制
lastInt = 5
SecondLast = 10
ThirdLast = -1
LastChar = a
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16594002

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档