【发布时间】:2013-09-06 11:32:33
【问题描述】:
我在玩元组和模板。我知道如果练习你会使用 boost::fusion (我认为)来做这种事情。我正在尝试在元组上实现 std::accumulate 的等价物。
下面是我的代码。据我所知,编译错误是由它尝试使用 4 模板参数版本引起的,而我打算使用 3 模板参数版本来完成递归。这意味着我错过了函数重载决议。
我原以为由于两个函数都可以匹配,所以它会选择 3 个模板参数版本作为更好的匹配,因为最后一个参数类型已明确说明。如果我将 std::tuple_size 作为附加模板参数添加到两个版本的 tuple_accumulate_helper,我仍然会得到相同的行为。
谁能建议我做错了什么?
#include <tuple>
template <std::size_t I>
struct int_{};
template <typename T, typename OutT, typename OpT, std::size_t IndexI>
auto tuple_accumulate_helper(T tuple, OutT init, OpT op, int_<IndexI>) -> decltype(tuple_accumulate_helper(tuple, op(init, std::get<IndexI>(tuple)), op, int_<IndexI + 1>()))
{
return tuple_accumulate_helper(tuple, op(init, std::get<IndexI>(tuple)), op, int_<IndexI + 1>());
}
template <typename T, typename OutT, typename OpT>
auto tuple_accumulate_helper(T tuple, OutT init, OpT op, int_<std::tuple_size<T>::value>) -> decltype(init)
{
return init;
}
template <typename T, typename OutT, typename OpT>
auto tuple_accumulate(T tuple, OutT init, OpT op) -> decltype(tuple_accumulate_helper(tuple, init, op, int_<0>()))
{
return tuple_accumulate_helper(tuple, init, op, int_<0>());
}
struct functor
{
template <typename T1, typename T2>
auto operator()(T1 t1, T2 t2) -> decltype(t1 + t2)
{
return t1 + t2;
}
};
int main(int argc, const char* argv[])
{
auto val = tuple_accumulate(std::make_tuple(5, 3.2, 7, 6.4f), 0, functor());
return 0;
}
【问题讨论】:
-
VS 是合规性落后者。使用coliru.stacked-crooked.com 或ideone.com 等在线编译器从更多最新的编译器安装中获取意见。根据 Clang 的说法,你有一个索引溢出错误,使用 index = 4 进入一个大小为 4 的元组。VC 说了什么?
-
你的代码看起来不错,除了 int_<:tuple_size>::value> 应该是 int_<:tuple_size>::value–1>。它没有在 gcc4.8.1 上编译。它适用于 msvc2013 v120。
-
通过 clang 运行它似乎当我期望它选择具有 3 个模板参数的重载时,它正在选择具有 4 个模板参数的重载,然后未能实例化 std::get 过去元组的结尾。