c++ - 如何拆分 tuple?

  显示原文与译文双语对照的内容
0 0

根据给定的

   template<typename First, typename... Tail>
   struct something
   {
       std::tuple<First, Tail...> t;
   };

我如何得到 std::tuple<Tail...>包含某元素 t第一台计算机除外?


一般情况下,我觉得这是个有趣的问题,但这是我的动力环境:

我想实现一个tuple的哈希。 我用这个应答作为基础。 我发现它时出现错误,那就是不给他们打电话, operator()hash对象的值为:

return left() ^ right();

应该是:

return left(std::get<0>(e)) ^ right(???);

在干什么呢? 该元组的将剩余的元素,继续递归实例化的模板编辑谓词。 以下是全部的代码,包括终止的情况:

#include <functional>
#include <utility>
namespace std
{
template<typename First, typename... Tail>
struct hash<std::tuple<First, Tail...>>
{
    typedef size_t result_type;
    typedef std::tuple<First, Tail...> argument_type;
    result_type operator()(argument_type const& e) const
    {
        std::hash<First> left;
        std::hash<std::tuple<Tail...>> right;
        return left(std::get<0>(e)) ^ right(???);
    }
};
template<>
struct hash<std::tuple<>>
{
    typedef size_t result_type;
    typedef std::tuple<> argument_type;
    result_type operator()(argument_type const& e) const
    {
        return 1;
    }
};
}
时间:原作者:6个回答

0 0

一起来看看锤子要先试试 可能的更好:

#include <tuple>
template < typename Target, typename Tuple, int N, bool end >
struct builder
{
    template < typename ... Args >
    static Target create(Tuple const& t, Args && ... args)
    {
        return builder<Target,Tuple, N+1, std::tuple_size<Tuple>::value == N+1>::create(t, std::forward<Args>(args)..., std::get<N>(t));
    }
};
template < typename Target, typename Tuple, int N >
struct builder<Target,Tuple,N,true>
{
    template < typename ... Args >
    static Target create(Tuple const& t, Args && ... args) { return Target(std::forward<Args>(args)...); }
};
template < typename Head, typename ... Tail >
std::tuple<Tail...> cdr(std::tuple<Head,Tail...> const& tpl)
{
    return builder<std::tuple<Tail...>, std::tuple<Head,Tail...>, 1, std::tuple_size<std::tuple<Head,Tail...>>::value == 1>::create(tpl);
}
#include <iostream>
int main() {
    std::tuple<int,char,double> t1(42,'e',16.7);
    std::tuple<char,double> t2 = cdr(t1);
    std::cout << std::get<0>(t2) << std::endl;
}

有一点需要注意的是,如果你使用自己的类型而不是std::tuple你或许是好得多了 原因是多么不容易,看来标准未指定此tuple的工作原理中,它不假设它从自身继承。 boost版本使用的缺点"物质可以通过挖掘。 这里有些东西或许更符合你想要的这样会让执行上述所有操作非常简单,强制转换:

template < typename ... Args > struct my_tuple;
template < typename Head, typename ... Tail >
struct my_tuple<Head,Tail...> : my_tuple<Tail...>
{
    Head val;
    template < typename T, typename ... Args >
    my_tuple(T && t, Args && ... args) 
        : my_tuple<Tail...>(std::forward<Args>(args)...)
        , val(std::forward<T>(t)) 
    {}
};
template < >
struct my_tuple <>
{
};

那是未经测试的,但应该可以说明这一点足以玩,直到它的工作原理。 即刻体验类型的对象" 尾巴",只需按照:

template < typename Head, typename ... Tail >
my_tuple<Tail...> cdr(my_tuple<Head,Tail...> const& mtpl) { return mtpl; }
原作者:
0 0

疯狂Eddie找到一条通往解包tuple,它做回答这个问题。 但是,对于特定的你提问的问题( 我如果不包含。 元组哈希),为什么不避免的所有元组而转而使用模板递归复制到hash中的每个元素圈?

#include <utility>
#include <iostream>
template< typename T >
size_t left( T const & ) {
  return 1;
}
template< int N, typename Head, typename... Tail >
struct _hash {
  typedef size_t result_type;
  typedef std::tuple< Head, Tail... > argument_type;
  result_type operator ()( argument_type const &e ) const {
    return left(std::get<N>(e)) ^ _hash<N-1, Head, Tail... >()(e);
  }
}; // end struct _hash
template< typename Head, typename... Tail >
struct _hash< 0, Head, Tail... > {
  typedef size_t result_type;
  typedef std::tuple< Head, Tail... > argument_type;
  result_type operator ()( argument_type const &e ) const {
    return left(std::get<0>(e));
  }
}; // end struct _hash< 0 >
template< typename Head, typename... Tail >
size_t hash( std::tuple< Head, Tail... > const &e ) {
  return _hash< sizeof...(Tail), Head, Tail... >()( e );
}
int main( ) {
  std::tuple< int > l_tuple( 5 );
  std::cout << hash( l_tuple ) << std::endl;
}

这并哈希次序反转,但xors是可互换所以无关紧要

原作者:
0 0

我在搜索同样的内容,想到了这个而直观C++14解决方案:

#include <iostream>
#include <tuple>
#include <utility>
template < typename T , typename... Ts >
auto head( std::tuple<T,Ts...> t )
{
   return  std::get<0>(t);
}
template < std::size_t... Ns , typename... Ts >
auto tail_impl( std::index_sequence<Ns...> , std::tuple<Ts...> t )
{
   return  std::make_tuple( std::get<Ns+1u>(t)... );
}
template < typename... Ts >
auto tail( std::tuple<Ts...> t )
{
   return  tail_impl( std::make_index_sequence<sizeof...(Ts) - 1u>() , t );
}
int main()
{
   auto t = std::make_tuple( 2, 3.14 , 'c' );
   std::cout << head(t) << std::endl;
   std::cout << std::get<0>( tail(t) ) << std::endl;
   std::cout << std::get<1>( tail(t) ) << std::endl;
}

所以,head( 。) 返回元组的第一个元素和最后一个N tail( 。) 返回一个新的元组只包含1 元素。

原作者:
0 0

如下所示:

#include <tuple>
template <bool, typename T, unsigned int ...N> struct tail_impl;
template <typename T, typename ...Args, unsigned int ...N>
struct tail_impl<false, std::tuple<T, Args...>, N...>
{
    static std::tuple<Args...> go(std::tuple<T, Args...> const & x)
    {
        return tail_impl<sizeof...(N) + 1 == sizeof...(Args), std::tuple<T, Args...>, N..., sizeof...(N)>::go(x);
    }
};
template <typename T, typename ...Args, unsigned int ...N>
struct tail_impl<true, std::tuple<T, Args...>, N...>
{
    static std::tuple<Args...> go(std::tuple<T, Args...> const & x)
    {
        return std::tuple<Args...>(std::get<N>(x)...);
    }
};
template <typename T, typename ...Args>
std::tuple<Args...> tail(std::tuple<T, Args...> const & x)
{
    return tail_impl<sizeof...(Args) == 1, std::tuple<T, Args...>, 0>::go(x);
}

测试:

#include <demangle.hpp>
#include <iostream>
typedef std::tuple<int, char, bool> TType;
int main()
{
    std::cout << demangle<TType>() << std::endl;
    std::cout << demangle<decltype(tail(std::declval<TType>()))>() << std::endl;
}

打印出:

std::tuple<int, char, bool>
std::tuple<char, bool>
原作者:
0 0

使用kgadek回答获取一部分std::tuple 和Andre Bergner是测试代码。? 这是简单好用但我不知道它是否是可移植的。

// works using gcc 4.6.3
// g++ -std=c++0x -W -Wall -g main.cc -o main
#include <iostream>
#include <tuple>
template < typename T , typename... Ts >
const T& head(std::tuple<T,Ts...> t)
{
   return  std::get<0>(t);
}
template <typename T, typename... Ts>
const std::tuple<Ts...>& tail(const std::tuple<T, Ts...>& t)
{
   return (const std::tuple<Ts...>&)t;
}
int main()
{
   auto t = std::make_tuple( 2, 3.14 , 'c' );
   std::cout << head(t) << std::endl;
   std::cout << std::get<0>( tail(t) ) << std::endl;
   std::cout << std::get<1>( tail(t) ) << std::endl;
}
原作者:
...