给出一个
template<typename First, typename... Tail>
struct something
{
std::tuple<First, Tail...> t;
};
Run Code Online (Sandbox Code Playgroud)
如何获得std::tuple<Tail...>
包含t
除第一个元素之外的所有元素的元素?
我认为这是一个有趣的问题,但这是我对背景的动机:
我想为元组实现哈希.我用这个答案作为基础.我发现它有一个错误,即没有调用operator()
带有值的哈希对象:
return left() ^ right();
Run Code Online (Sandbox Code Playgroud)
应该:
return left(std::get<0>(e)) ^ right(???);
Run Code Online (Sandbox Code Playgroud)
??? 将是元组的剩余元素继续模板的递归实例化.以下是完整的代码,包括终止部分:
#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;
}
};
}
Run Code Online (Sandbox Code Playgroud)
And*_*ner 13
我正在寻找相同的东西,并提出了这个相当直接的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;
}
Run Code Online (Sandbox Code Playgroud)
因此,head(.)返回元组的第一个元素,tail(.)返回仅包含最后N-1个元素的新元组.
像这样的东西:
#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);
}
Run Code Online (Sandbox Code Playgroud)
测试:
#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;
}
Run Code Online (Sandbox Code Playgroud)
印刷:
std::tuple<int, char, bool>
std::tuple<char, bool>
Run Code Online (Sandbox Code Playgroud)