我尝试创建一个对std::vector
的所有元素求和的函数:
template<typename IteratorT>
auto sum(IteratorT first, IteratorT last) -> decltype(*first) {
decltype(*first) sum = 0;
for (; first != last; ++first)
sum += *first;
return sum;
}
我收到了这个错误:
无法从'int'转换为'int&amp;'
经过一些研究后我发现了这个:std::iterator_traits<IteratorT>::difference_type
。将我的代码更改为:
template<typename IteratorT>
auto sum(IteratorT first, IteratorT last) -> typename std::iterator_traits<IteratorT>::difference_type {
std::iterator_traits<IteratorT>::difference_type sum = 0;
for (; first != last; ++first)
sum += *first;
return sum;
}
它确实有效,但我不确定为什么以及它是否是一个好的解决方案。总之,我有两个问题:
1)为什么decltype(*first)
会像我预期的那样返回int&
而不是int
2)typename
之前的std::iterator_traits<IteratorT>::difference_type
到底是什么以及为什么sum
功能在我删除后无法正常工作
答案 0 :(得分:0)
decltype(*first)
返回引用,否则我们将无法编写
*first = 7;
关于difference_type
,我们不清楚你要做什么。单词typename
是必需的,以告诉编译器所谓的依赖类型(通常情况是::
之后的任何类型)是模板而不是值。
答案 1 :(得分:0)
试试这个:
#include <type_traits>
template <
typename Iter,
typename Ret = typename std::decay<decltype(*std::declval<Iter>())>::type>
Ret f(Iter first, Iter last)
{
Ret sum {};
for (; first != last; ++first) { sum += *first; }
return sum;
}
答案 2 :(得分:0)
有两个主要问题:
aa dereferenced iterator的类型是引用,它可以是const
,而对于std::vector
,它可以与vector的项类型非常不同。
当项目类型为例如bool
,您不希望以bool
类型执行总和。
以下代码是一个解决方案:
#include <iterator> // std::iterator_traits
template< class Iter >
auto sum( Iter first, Iter last )
-> decltype( typename std::iterator_traits<Iter>::value_type() + 0 )
{
decltype( typename std::iterator_traits<Iter>::value_type() + 0 ) sum = 0;
for (; first != last; ++first)
sum += *first;
return sum;
}
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define ITEMS( x ) begin( x ), end( x )
auto main()
-> int
{
vector<double> const v1 = {3, 1, 4, 1, 5};
cout << sum( ITEMS(v1) ) << endl;
vector<bool> const v2 = {0, 1, 1, 0, 1};
cout << sum( ITEMS( v2) ) << endl;
}
请注意,您无需定义自己的sum
:std::accumulate
。
答案 3 :(得分:-1)
你随机做了一件事,它是随机的。 distance_type
与您的问题无关,它是一种表示测量两个迭代器之间距离的结果的类型。由于它通常是整数类型,因此您最终能够在算术中使用它。
最初的问题是由于解除引用迭代器会返回一个指向底层对象的(const)指针这一事实 - 这是需要的,所以像
这样的代码*it = 10;
会做你想做的事情(或者无法为const迭代器编译)。
typename
关键字是必需的,但此处已typename
使用此处有足够的重复项。