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

C++11 对于std::tuple,如何按类型获取数据,以及如何按索引获取类型?,c++11,C++11,标题是这样写的:给定一个std::tuple,我想 获取给定类型的第一个元素 获取第i个元素的类型 STL是否提供解决方案?还是一种解决方法?有人能完成我的代码吗 #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::ge

标题是这样写的:给定一个std::tuple,我想

  • 获取给定类型的第一个元素
  • 获取第i个元素的类型
  • STL是否提供解决方案?还是一种解决方法?有人能完成我的代码吗

    #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;
    }
    
    按类型(而不是索引)从元组中获取值 从C++11开始,没有STL方法获取类型为
    T
    的元组的第一个元素
    在C++14中,应该有一种方法可以使用新的重载
    std::get
    来执行您想要的操作。ISO纸张位于此处和此处

    您可以在C++11中通过以下操作完成此操作:

    #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);
    }
    
    获取元组中第n个元素的类型
    有一种方法可以获得第n个元素的类型
    std::tuple\u element::type
    (谢谢@syam)是tuple的第n个元素的类型。

    只是为了搞笑,定义的不是你想要的,并且在某种意义上是非常有限的,你必须添加新的类型,它可以反向工作,但是这里有一个
    getnthtyperverse
    ,它只支持'int'和'char'类型哈哈


    谢谢,您可以提供另一种使用boost或自行编写的解决方法吗?
    decltype(std::get(tuple))
    将产生
    T&
    const T&
    ,具体取决于选择的
    std::get
    版本(这又取决于
    tuple
    constness——我认为我们可以安全地忽略
    T&&
    的情况,因为它需要抛出
    std::move
    )。最好使用
    std::tuple\u元素::type
    来获得“裸的”键入IMHO。@syam我在您的第n种类型的更改中添加了内容。例如:--哦,我们可能需要在
    get
    函数上分别使用
    const&
    &
    &
    重载,这样我们就可以分别通过
    const T&
    &
    std::move
    返回。@Johannes我编辑了这篇文章的第二部分ost将包含您想要的三个重载--
    tuple&
    tuple const&
    tuple&
    。我真的很好奇您为什么要使用这样的tuple。我的直觉告诉我,您应该重新考虑您试图解决的问题的方法。
    #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);
    }
    
    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";
    }
    
    //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));
    }
    
    #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;
    }
    
    lastInt = 5
    SecondLast = 10
    ThirdLast = -1
    LastChar = a