Итератор с шагом
Попытался скомпилировать код итератора с шагом из книги C++ Cookbook By Jeff Cogswell, Christopher Diggins, Ryan Stephens, Jonathan Turkanis.
Класс stride_iter
должен позволять обращаться к элементам не подряд, а к каждому
2-му, 3-му и т.д.
// код немного изменён мной: добавлен const и operator-
#include <iterator>
#include <cassert>
template<class Iter_T>
class stride_iter
{
public:
// public typedefs
typedef typename std::iterator_traits<Iter_T>::value_type value_type;
typedef typename std::iterator_traits<Iter_T>::reference reference;
typedef typename std::iterator_traits<Iter_T>::difference_type
difference_type;
typedef typename std::iterator_traits<Iter_T>::pointer pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef stride_iter self;
// constructors
stride_iter() : m(NULL), step(0) {};
stride_iter(const self& x) : m(x.m), step(x.step) {}
stride_iter(Iter_T x, difference_type n) : m(x), step(n) {}
// operators
self& operator++() { m += step; return *this; }
self operator++(int) { self tmp = *this; m += step; return tmp; }
self& operator+=(difference_type x) { m += x * step; return *this; }
self& operator--() { m -= step; return *this; }
self operator--(int) { self tmp = *this; m -= step; return tmp; }
self& operator-=(difference_type x) { m -= x * step; return *this; }
reference operator[](difference_type n) const { return m[n * step]; }
reference operator*() const { return *m; }
// friend operators
friend bool operator==(const self& x, const self& y) {
assert(x.step == y.step);
return x.m == y.m;
}
friend bool operator!=(const self& x, const self& y) {
assert(x.step == y.step);
return x.m != y.m;
}
friend bool operator<(const self& x, const self& y) {
assert(x.step == y.step);
return x.m < y.m;
}
friend difference_type operator-(const self& x, difference_type y) {
assert(x.step == y.step);
return x -= y * x.step;
}
friend difference_type operator-(const self& x, const self& y) {
assert(x.step == y.step);
return (x.m - y.m) / x.step;
}
friend self operator+(const self& x, difference_type y) {
assert(x.step == y.step);
return x += y * x.step;
}
friend self operator+(difference_type x, const self& y) {
assert(x.step == y.step);
return y += x * x.step;
}
private:
Iter_T m;
difference_type step;
};
Вот как я пытаюсь использовать этот класс (в настройках проекта C++ 20, указывать шаблонный параметр не надо. Если указать, это не поможет):
std::vector<double> v( 100 ); // отсортируем каждый 10й элемент
stride_iter b{ v.begin(),10};
stride_iter e{ v.end(),10};
std::sort(b, e);
Этот код, однако, не компилируется.
double test[100]; // отсортируем каждый 10й элемент
stride_iter b{ test,10 };
stride_iter e{ test+100,10 };
std::sort(b, e);
Тут UB, но это не важно, т.к. этот код тоже не компилируется. MSVC выдаёт ошибку:
test.cpp
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14): error C2672: "std::_Med3_unchecked": не найдена соответствующая перегруженная функция
(компиляция исходного файла "/test.cpp")
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8265,19):
может быть "void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14):
"void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)": в шаблон параметр "_RanIt" неоднозначен
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14):
может быть "_RanIt"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14):
или "__int64"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14):
'void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)': не удалось вывести аргумент шаблон для '_RanIt' из '_RanIt'
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8289,14):
контекст создания экземпляра шаблона (сначала самый старый)
C:\myprogs\luamodules\luamkl\test.cpp(10,10):
выполняется компиляция ссылки на экземпляр шаблон функции "void std::sort<stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>>>(const _RanIt,const _RanIt)"
with
[
_Ty=double,
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8408,10):
выполняется компиляция ссылки на экземпляр шаблон функции "void std::sort<_RanIt,std::less<void>>(const _RanIt,const _RanIt,_Pr)"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>,
_Pr=std::less<void>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8403,10):
выполняется компиляция ссылки на экземпляр шаблон функции "void std::_Sort_unchecked<_RanIt,_Fn>(_RanIt,_RanIt,__int64,_Pr)"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>,
_Fn=std::less<void>,
_Pr=std::less<void>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8384,26):
выполняется компиляция ссылки на экземпляр шаблон функции "std::pair<_RanIt,_RanIt> std::_Partition_by_median_guess_unchecked<_RanIt,_Pr>(_RanIt,_RanIt,_Pr)"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>,
_Pr=std::less<void>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8301,10):
выполняется компиляция ссылки на экземпляр шаблон функции "void std::_Guess_median_unchecked<_RanIt,_Pr>(_RanIt,_RanIt,_RanIt,_Pr)"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>,
_Pr=std::less<void>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8290,14): error C2672: "std::_Med3_unchecked": не найдена соответствующая перегруженная функция
(компиляция исходного файла "/test.cpp")
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8265,19):
может быть "void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8290,14):
"void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)": в шаблон параметр "_RanIt" неоднозначен
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8290,14):
может быть "_RanIt"
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8290,14):
или "__int64"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8290,14):
'void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)': не удалось вывести аргумент шаблон для '_RanIt' из '_RanIt'
with
[
_RanIt=stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8291,14): error C2672: "std::_Med3_unchecked": не найдена соответствующая перегруженная функция
(компиляция исходного файла "/test.cpp")
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8265,19):
может быть "void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8291,14):
"void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)": в шаблон параметр "_RanIt" неоднозначен
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8291,14):
может быть "__int64"
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8291,14):
или "stride_iter<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>>"
with
[
_Ty=double
]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\algorithm(8291,14):
'void std::_Med3_unchecked(_RanIt,_RanIt,_RanIt,_Pr)': не удалось вывести аргумент шаблон для '_RanIt' из '__int64'
А вот код из STL, на котором выдаётся ошибка:
template <class _RanIt, class _Pr>
_CONSTEXPR20 void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) {
// sort median element to middle
using _Diff = _Iter_diff_t<_RanIt>;
const _Diff _Count = _Last - _First;
if (40 < _Count) { // Tukey's ninther
const _Diff _Step = (_Count + 1) >> 3; // +1 can't overflow because range was made inclusive in caller
const _Diff _Two_step = _Step << 1; // note: intentionally discards low-order bit
_STD _Med3_unchecked(_First, _First + _Step, _First + _Two_step, _Pred);
_STD _Med3_unchecked(_Mid - _Step, _Mid, _Mid + _Step, _Pred); // здесь ошибка
_STD _Med3_unchecked(_Last - _Two_step, _Last - _Step, _Last, _Pred);
_STD _Med3_unchecked(_First + _Step, _Mid, _Last - _Step, _Pred);
} else {
_STD _Med3_unchecked(_First, _Mid, _Last, _Pred);
}
}
Что происходит?
Источник: Stack Overflow на русском