C++ C++;:在计算迭代器之间的距离时被类型所迷惑
我需要旋转C++ C++;:在计算迭代器之间的距离时被类型所迷惑,c++,algorithm,c++11,iterator,C++,Algorithm,C++11,Iterator,我需要旋转std::vector中的元素,以便它在开始时保存第一个重复的元素。更清楚地说,如果我有: 1 2 3 4 5 6 3 7 8 那么我想: 3 4 5 6 3 7 8 1 2 好的,让我们使用std::rotate(),并构建一个函数来获取第一个重复位置: int main() { std::vector<int> v = { 1,2,3,4,5,6,3,7,8 }; auto it = FindFirstDuplicate(v); cout &
std::vector
中的元素,以便它在开始时保存第一个重复的元素。更清楚地说,如果我有:
1 2 3 4 5 6 3 7 8
那么我想:
3 4 5 6 3 7 8 1 2
好的,让我们使用std::rotate()
,并构建一个函数来获取第一个重复位置:
int main() {
std::vector<int> v = { 1,2,3,4,5,6,3,7,8 };
auto it = FindFirstDuplicate(v);
cout << "first dupe is " << *it << " at " << it - v.begin() << endl;
std::rotate( v.begin(), it, v.end() );
}
为了节省您的时间,我没有发布错误消息,但对我来说,编译器似乎在最后一行抱怨不同类型的迭代器。我还尝试对it1
使用非常量迭代器,但仍然遇到了这个问题
非常感谢您在迭代器问题上提供的任何帮助,以及关于算法本身的任何建议。问题在于您试图从
常量引用返回迭代器。您可以在这个最小的示例中看到问题:
#include <iostream>
#include <vector>
template <typename T>
typename std::vector<T>::iterator foo(const std::vector<T>& v)
{
return v.begin(); // const overload returns const_iterator
}
int main() {
std::vector<int> v(42);
foo(v); // Instantiate function template: ERROR
}
#包括
#包括
模板
typename std::vector::迭代器foo(const std::vector&v)
{
return v.begin();//常量重载返回常量迭代器
}
int main(){
std::向量v(42);
foo(v);//实例化函数模板:错误
}
您可以做的是将非常量引用传递给finder函数:
template<typename T>
typename vector<T>::iterator FindFirstDuplicate( vector<T>& v )
{
...
模板
typename vector::迭代器FindFirstDuplicate(vector&v)
{
...
对于记录,正如@James Kanze(归功于他)所建议的,这里是一个较短、已更正且已完成的版本。此版本还返回找到的副本的位置
template<typename T>
typename vector<T>::iterator
FindFirstDuplicate( vector<T>& v, typename vector<T>::iterator& dupe )
{
auto current = v.begin();
while (
current != v.end() &&
(dupe = std::find( std::next( current ), v.end(), *current )) == v.end()
)
{
++current;
}
return current;
}
// test case
int main()
{
vector<int> v = { 1,2,3,4,5,6,5,4,3 };
auto dupe = v.begin();
auto it = FindFirstDuplicate(v,dupe);
cout << "first dupe is " << *it << " at pos " << it - v.cbegin() << endl;
cout << "dupe is " << *dupe << " at pos " << dupe - v.cbegin() << endl;
}
模板
类型名向量::迭代器
FindFirstDuplicate(vector&v,typename vector::iterator&dupe)
{
自动电流=v.开始();
当(
当前!=v.结束()&&
(dupe=std::find(std::next(当前),v.end(),*当前))==v.end()
)
{
++电流;
}
回流;
}
//测试用例
int main()
{
向量v={1,2,3,4,5,6,5,4,3};
自动复制=v.开始();
自动it=FindFirstDuplicate(v,dupe);
在findFirstDuplicate
中不需要临时向量吗?就像while(current!=end&&std::find(std::next(current),end,*current)!=end){++current;}
就足够了(使用current
和end
初始化为v.begin()
).好的,谢谢。但是如果我更愿意保留它只是为了可读性的目的,编译器难道不能优化它吗?我个人喜欢这样的想法,即不要试图自己对代码进行过度优化,并将其传递给编译器。我发现没有额外变量的版本更清晰:它非常清楚地表明您在同一个向量中寻找重复的代码(而不是其他地方)并且它避免了复杂的迭代器算法来确定返回值。@James Kanze好的,我明白了,我会试试。我只是不熟悉std::next()
,所以我一眼就不太清楚。但我喜欢学习新技巧,谢谢!@James Kanze我发布了你建议的完整版本,只做了一点小小的修改,谢谢。哇,太简单了……我被(像往常一样)过于冗长的错误消息愚弄了,甚至没有考虑检查参数constness。谢谢。
template<typename T>
typename vector<T>::iterator
FindFirstDuplicate( vector<T>& v, typename vector<T>::iterator& dupe )
{
auto current = v.begin();
while (
current != v.end() &&
(dupe = std::find( std::next( current ), v.end(), *current )) == v.end()
)
{
++current;
}
return current;
}
// test case
int main()
{
vector<int> v = { 1,2,3,4,5,6,5,4,3 };
auto dupe = v.begin();
auto it = FindFirstDuplicate(v,dupe);
cout << "first dupe is " << *it << " at pos " << it - v.cbegin() << endl;
cout << "dupe is " << *dupe << " at pos " << dupe - v.cbegin() << endl;
}