编写一个最小的自定义运算符:std :: sort需要std :: __ lg为我的类型定义

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写一个最小的自定义运算符:std :: sort需要std :: __ lg为我的类型定义相关的知识,希望对你有一定的参考价值。

作为练习,我正在尝试编写一个由std::sort使用的自定义迭代器。从其文档中,我读到:

[我的迭代器]必须符合ValueSwappable和的要求 RandomAccessIterator

没有完全实现那些,我来到这个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,

demo from coliru

为什么我会收到此错误以及如何解决?


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需要std :: __ lg为我的类型定义的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::sort 对对象向量进行排序

如果比较函数不是运算符 <,为啥 std::sort 会崩溃?

自定义类没有可行的重载运算符 []

std :: sort不会移动向量的元素[关闭]

Doctrine DQL 中的自定义运算符

关于Lucene的自定义Sort排序