长话短说
给定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
build 。 是否有更好的方法从范围中获取类型?请注意 R
不一定是容器,所以我不能使用 R::value_type
.
请注意,我使用的是 Visual Studio 2013,因此我可以使用大部分 C++11 和部分 C++14。
附言。对实现还有其他意见吗?有什么缺点或影响吗?
最佳答案
你可以使用 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));
}
关于c++ - 从模板范围获取类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28738638/