![](/img/trans.png)
[英]C++11 std::tuple to std::array conversion causes variadic template crash
[英]Recursive variadic template terminated by std::tuple_size in C++11
我在实现递归模板(模板结构中的函数)时遇到问题,该模板将由std :: tuple_size终止。
这是代码片段(为简化问题,我简化了代码):
template<int index, typename ...T_arguments>
struct Helper
{
static void func (size_t& return_size,
const std::tuple<T_arguments...>& arguments)
{
const auto& argument (std::get<index> (arguments));
return_size += ::value_size (argument);
::Helper<index + 1, T_arguments...>::func (return_size, arguments);
}
// ...
template<typename... T_arguments>
struct Helper<std::tuple_size<T_arguments...>::value, T_arguments...>
{
static void func (size_t& return_size,
const std::tuple<T_arguments...>& arguments)
{
const auto& argument (std::get<std::tuple_size<T_arguments...>::value> (arguments));
return_size += ::value_size (argument);
}
初始模板调用如下所示:
Helper<0, T_arguments...>::func (return_size, arguments);
GCC失败并显示错误:
错误:模板参数'std :: tuple_size :: value'涉及模板参数struct Helper :: value,T_arguments ...>
std::tuple_size
声称在编译时是已知的,那么为什么我不能使用它进行模板专门化?
实际上,§14.5.4/ 9禁止您在做什么,
部分自定义的非类型自变量表达式不应包含部分自定义的模板参数,除非自变量表达式是简单标识符。
以下内容可能会有所帮助:
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
total_value_size(size_t& return_size, const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
total_value_size(size_t& return_size, const std::tuple<Tp...>& t)
{
const auto& argument (std::get<I> (t));
return_size += ::value_size(argument);
total_value_size<I + 1, Tp...>(return_size, t);
}
使用index_sequence和基于范围的。
#include <cstdlib>
#include <cstddef>
#include <tuple>
namespace mpl
{
template< std::size_t ... I>
struct index_sequence
{
};
template< std::size_t s, typename I1, typename I2>
struct concate;
template< std::size_t s, std::size_t ...I, std::size_t ...J>
struct concate<s, index_sequence<I...>, index_sequence<J...> >
{
typedef index_sequence<I... ,( J + s)... > type;
};
template< std::size_t N>
struct make_index_sequence
{
typedef typename concate< N/2,
typename make_index_sequence< N/2>::type,
typename make_index_sequence< N - N/2>::type
>::type type;
};
template<>struct make_index_sequence<0>
{
typedef index_sequence<> type;
};
template<> struct make_index_sequence<1>
{
typedef index_sequence<0> type;
};
template< typename ...T>
struct index_sequence_for
{
typedef typename make_index_sequence< sizeof...(T) > ::type type;
};
} // mpl
template< typename T >
std::size_t value_size( T ){ return sizeof(T); }// only for illustration
template< typename ...Tp, std::size_t ...i>
std::size_t total_value_size_impl( const std::tuple<Tp...> & t, mpl::index_sequence<i...> )
{
std::size_t result=0;
for(auto x: { value_size( std::get<i>(t) ) ... } )
{
result += x;
}
return result;
}
template< typename ...Tp>
std::size_t total_value_size( const std::tuple<Tp...> & t)
{
typedef typename mpl::index_sequence_for<Tp...> :: type indexes;
return total_value_size_impl( t, indexes{} );
}
#include <cstdio>
int main()
{
typedef std::tuple<int, char, double> types;
std::size_t result = total_value_size(types{});
printf("%d\n", result);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.