将R
作为模板参数,R
为some_container<T>
或T[]
,如何推断T
?
可能的实施是std::iterator_traits<decltype(std::begin(r))>::value_type
,寻找不那么详细的东西。
我正在尝试围绕std::accumulate
算法实现一个包装器,所以不要输入这个:
std::accumulate(v.begin(), v.end(), 0, [](int x, int y) { return x * y; });
用户只需写下:
my::accumulate(v, [](int x, int y) { return x * y; });
基本上,给定一个实体和一个操作,my::accumulate
旨在使用以下参数调用std::accumulate
:
std::begin()
std::end()
我使用免费的begin
和end
函数来允许函数在内置数组上工作。因此,传递的实体是范围。这是我的实施:
template<class R, typename F>
auto accumulate(const R& r, F&& f) ->
typename std::iterator_traits<decltype(std::begin(r))>::value_type
{
using T = std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}
工作正常。唯一困扰我的是丑陋的std::iterator_traits<decltype(std::begin(r))>::value_type
建筑。 是否有更好的方法从范围中获取类型?请注意,R
不必是容器,因此我无法使用R::value_type
。
请注意,我使用的是Visual Studio 2013,因此我可以使用大部分C ++ 11和一些C ++ 14。
PS。有关实施的任何其他意见?有任何缺点或影响吗?
答案 0 :(得分:1)
您可以使用typename std::remove_reference_t<decltype(*std::begin(r))>
来保存一些按键,但效果不是很好。
我想您要实现的算法不仅仅是accumulate
,在这种情况下,您可以为元素类型创建别名:
template<typename T>
using value_type = typename std::iterator_traits<decltype(std::begin(T{}))>::value_type;
template<class R, typename F>
value_type<R> accumulate(const R& r, F&& f)
{
return std::accumulate(std::begin(r), std::end(r), value_type<R>{}, std::forward<F>(f));
}
否则,您可以使用占位符返回类型来避免重复:
template<class R, typename F>
auto accumulate(const R& r, F&& f)
{
using T = typename std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}