编写一个最小的自定义运算符:std::sort 需要为我的类型定义 std::__lg
Write a minimal custom operator: std::sort requires std::__lg to be degined for my type
作为练习,我正在尝试编写一个供 std::sort
使用的自定义迭代器。从它的文档中,我读到:
[My iterator] must meet the requirements of ValueSwappable and
RandomAccessIterator.
没有完全实现那些1,我来到这个 MCVE:
#include <iostream>
#include <algorithm>
struct mcve_random_access_iterator
{
using size_type = std::size_t;
using value_type = int;
size_type _index;
value_type* _values;
mcve_random_access_iterator(value_type* values) : _index(0), _values(values) {}
mcve_random_access_iterator& operator-(const mcve_random_access_iterator& rhs) { _index-=rhs._index ; return *this; }
value_type& operator*() { return _values[_index]; }
friend bool operator==(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs) { return lhs._index == rhs._index; }
friend bool operator!=(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs) { return !(lhs == rhs); }
};
void swap(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs)
{
std::swap(*lhs, *rhs);
}
struct mcve_container
{
int _values[3];
mcve_container() : _values{2, 3, 1} {}
mcve_random_access_iterator begin() { return {_values}; }
mcve_random_access_iterator end() { auto b = begin(); b._index = sizeof(_values)/sizeof(_values[0]); return b; }
};
int main()
{
mcve_container data;
std::sort(data.begin(), data.end());
for (auto n : data._values)
std::cout << n << ", ";
std::cout << "\n";
}
用g++ 7.2.0编译,出现如下错误:
/usr/local/include/c++/7.2.0/bits/stl_algo.h:1969:14: error: no matching function for call to '__lg(mcve_random_access_iterator&)'
std::__lg(__last - __first) * 2,
为什么会出现此错误以及如何解决?
1) 我已经从 mcve_random_access_iterator
中删除了 RandomAccessIterator 的所有要求,但仍然会重现错误。
两个 RandomAccessIterators 之间的区别是 std::iterator_traits<It>::difference_type
类型的数字(具体来说,是描述一个迭代器与另一个迭代器之间有多少元素的数字)。你的不是。
std::__lg
是一条红鲱鱼,相关部分是它期望与您的 __last - __first
提供的类型不同。
http://en.cppreference.com/w/cpp/concept/RandomAccessIterator(见表达式b - a
对应的要求)
完成@milleniumbug 的回答:这是适用于 std::sort
的自定义迭代器的最小工作实现。
struct random_access_iterator
{
using size_type = std::size_t;
using value_type = int;
using difference_type = std::size_t;
using reference = int&;
size_type _index;
value_type* _values;
random_access_iterator(value_type* values) : _index(0), _values(values) {}
random_access_iterator(random_access_iterator const& other) : _index(other._index), _values(other._values) {}
random_access_iterator& operator=(random_access_iterator const& other) { _index = other._index ; _values = other._values; return *this;}
// Iterator
value_type& operator*() { return _values[_index]; }
random_access_iterator& operator++() { ++_index; return *this; }
// InputIterator
friend bool operator==(random_access_iterator& lhs, random_access_iterator& rhs) { return lhs._index == rhs._index; }
friend bool operator!=(random_access_iterator& lhs, random_access_iterator& rhs) { return !(lhs == rhs); }
value_type& operator->() { return _values[_index]; }
random_access_iterator operator++(int) { const auto tmp = *this; ++*this; return tmp; }
// ForwardIterator
random_access_iterator() : _index(0), _values(nullptr) {}
// BidirectionalIterator
random_access_iterator& operator--() { --_index; return *this; }
random_access_iterator operator--(int) { const auto tmp = *this; --*this; return tmp; }
// RandomAccessIterator
random_access_iterator& operator+=(difference_type rhs) { _index+=rhs; return *this; }
friend random_access_iterator operator+(random_access_iterator const& lhs, difference_type rhs) { auto tmp = lhs; tmp+=rhs; return tmp; }
friend random_access_iterator operator+(difference_type lhs, random_access_iterator const& rhs) { return rhs + lhs; }
random_access_iterator& operator-=(difference_type rhs) { _index-=rhs; return *this; }
friend random_access_iterator operator-(random_access_iterator const& lhs, difference_type rhs) { auto tmp = lhs; tmp-=rhs; return tmp; }
friend random_access_iterator operator-(difference_type lhs, random_access_iterator const& rhs) { return rhs - lhs; }
friend difference_type operator-(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index - rhs._index; }
reference operator[](size_type i) const { return *(*this + i); }
friend bool operator<(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index < rhs._index; }
friend bool operator<=(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index <= rhs._index; }
friend bool operator>(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index > rhs._index; }
friend bool operator>=(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index >= rhs._index; }
};
namespace std
{
template<>
struct iterator_traits<random_access_iterator>
{
using size_type = random_access_iterator::size_type;
using value_type = random_access_iterator::value_type;
using difference_type = random_access_iterator::difference_type;
using reference = random_access_iterator::reference;
using iterator_category = random_access_iterator_tag;
};
}
void swap(random_access_iterator& lhs, random_access_iterator& rhs)
{
std::swap(*lhs, *rhs);
}
我写了一个简单的现场演示来看看this iterator in action with std::sort
。
作为练习,我正在尝试编写一个供 std::sort
使用的自定义迭代器。从它的文档中,我读到:
[My iterator] must meet the requirements of ValueSwappable and
RandomAccessIterator.
没有完全实现那些1,我来到这个 MCVE:
#include <iostream>
#include <algorithm>
struct mcve_random_access_iterator
{
using size_type = std::size_t;
using value_type = int;
size_type _index;
value_type* _values;
mcve_random_access_iterator(value_type* values) : _index(0), _values(values) {}
mcve_random_access_iterator& operator-(const mcve_random_access_iterator& rhs) { _index-=rhs._index ; return *this; }
value_type& operator*() { return _values[_index]; }
friend bool operator==(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs) { return lhs._index == rhs._index; }
friend bool operator!=(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs) { return !(lhs == rhs); }
};
void swap(mcve_random_access_iterator& lhs, mcve_random_access_iterator& rhs)
{
std::swap(*lhs, *rhs);
}
struct mcve_container
{
int _values[3];
mcve_container() : _values{2, 3, 1} {}
mcve_random_access_iterator begin() { return {_values}; }
mcve_random_access_iterator end() { auto b = begin(); b._index = sizeof(_values)/sizeof(_values[0]); return b; }
};
int main()
{
mcve_container data;
std::sort(data.begin(), data.end());
for (auto n : data._values)
std::cout << n << ", ";
std::cout << "\n";
}
用g++ 7.2.0编译,出现如下错误:
/usr/local/include/c++/7.2.0/bits/stl_algo.h:1969:14: error: no matching function for call to '__lg(mcve_random_access_iterator&)' std::__lg(__last - __first) * 2,
为什么会出现此错误以及如何解决?
1) 我已经从 mcve_random_access_iterator
中删除了 RandomAccessIterator 的所有要求,但仍然会重现错误。
两个 RandomAccessIterators 之间的区别是 std::iterator_traits<It>::difference_type
类型的数字(具体来说,是描述一个迭代器与另一个迭代器之间有多少元素的数字)。你的不是。
std::__lg
是一条红鲱鱼,相关部分是它期望与您的 __last - __first
提供的类型不同。
http://en.cppreference.com/w/cpp/concept/RandomAccessIterator(见表达式b - a
对应的要求)
完成@milleniumbug 的回答:这是适用于 std::sort
的自定义迭代器的最小工作实现。
struct random_access_iterator
{
using size_type = std::size_t;
using value_type = int;
using difference_type = std::size_t;
using reference = int&;
size_type _index;
value_type* _values;
random_access_iterator(value_type* values) : _index(0), _values(values) {}
random_access_iterator(random_access_iterator const& other) : _index(other._index), _values(other._values) {}
random_access_iterator& operator=(random_access_iterator const& other) { _index = other._index ; _values = other._values; return *this;}
// Iterator
value_type& operator*() { return _values[_index]; }
random_access_iterator& operator++() { ++_index; return *this; }
// InputIterator
friend bool operator==(random_access_iterator& lhs, random_access_iterator& rhs) { return lhs._index == rhs._index; }
friend bool operator!=(random_access_iterator& lhs, random_access_iterator& rhs) { return !(lhs == rhs); }
value_type& operator->() { return _values[_index]; }
random_access_iterator operator++(int) { const auto tmp = *this; ++*this; return tmp; }
// ForwardIterator
random_access_iterator() : _index(0), _values(nullptr) {}
// BidirectionalIterator
random_access_iterator& operator--() { --_index; return *this; }
random_access_iterator operator--(int) { const auto tmp = *this; --*this; return tmp; }
// RandomAccessIterator
random_access_iterator& operator+=(difference_type rhs) { _index+=rhs; return *this; }
friend random_access_iterator operator+(random_access_iterator const& lhs, difference_type rhs) { auto tmp = lhs; tmp+=rhs; return tmp; }
friend random_access_iterator operator+(difference_type lhs, random_access_iterator const& rhs) { return rhs + lhs; }
random_access_iterator& operator-=(difference_type rhs) { _index-=rhs; return *this; }
friend random_access_iterator operator-(random_access_iterator const& lhs, difference_type rhs) { auto tmp = lhs; tmp-=rhs; return tmp; }
friend random_access_iterator operator-(difference_type lhs, random_access_iterator const& rhs) { return rhs - lhs; }
friend difference_type operator-(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index - rhs._index; }
reference operator[](size_type i) const { return *(*this + i); }
friend bool operator<(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index < rhs._index; }
friend bool operator<=(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index <= rhs._index; }
friend bool operator>(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index > rhs._index; }
friend bool operator>=(random_access_iterator const& lhs, random_access_iterator const& rhs) { return lhs._index >= rhs._index; }
};
namespace std
{
template<>
struct iterator_traits<random_access_iterator>
{
using size_type = random_access_iterator::size_type;
using value_type = random_access_iterator::value_type;
using difference_type = random_access_iterator::difference_type;
using reference = random_access_iterator::reference;
using iterator_category = random_access_iterator_tag;
};
}
void swap(random_access_iterator& lhs, random_access_iterator& rhs)
{
std::swap(*lhs, *rhs);
}
我写了一个简单的现场演示来看看this iterator in action with std::sort
。