2017-01-14 8 views
0

スマートなイテレータを開発しようとしていますが、ソートを使用しているときに単純なイテレータを作成してもクラッシュします。iteratorがstd :: sortでクラッシュしました

ループの範囲は正常に機能しましたが、std :: sortはうまく機能しませんでした。

#include <iostream> 
#include <vector> 
#include <algorithm> 

using namespace std; 

template<typename I> 
class it { 
public: 
    it(I i) : i(i){} 
    using iterator_category = std::random_access_iterator_tag; 
    using value_type = typename I::value_type; 
    using difference_type = std::ptrdiff_t; 
    using pointer = typename I::pointer; 
    using reference = typename I::reference; 
    value_type &operator*() { 
     return *i; 
    } 

    it &operator++() { 
     ++i; 
     return *this; 
    } 

    it &operator--() { 
     --i; 
     return *this; 
    } 

    bool operator!=(it a) { 
     return a.i != i; 
    } 

    it &operator+(std::size_t n) { 
     i += n; 
     return *this; 
    } 

    it &operator-(std::size_t n) { 
     i -= n; 
     return *this; 
    } 

    std::ptrdiff_t operator-(it a) { 
     return i - a.i; 
    } 

    bool operator==(it a) { 
     return a.i == i; 
    } 

    bool operator<(it a) { 
     return i < a.i; 
    } 

private: 
    I i; 
}; 

int main() 
{ 
    std::vector<int> v = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 

    for(auto e : v) 
     std::cout << e << " "; 
    std::cout << std::endl; 

    std::sort(it<decltype(v.begin())>(v.begin()), it<decltype(v.end())>(v.end())); 

    for(auto e : v) 
     std::cout << e << " "; 
    std::cout << std::endl; 

    return 0; 
} 

クラッシュは、ここでは "打ち鳴らすコード" で起こる(gdbがあることを教えてください):それはそれをdeferrence時にそれが起こった

struct _Iter_less_iter 
    { 
    template<typename _Iterator1, typename _Iterator2> 
     _GLIBCXX14_CONSTEXPR 
     bool 
     operator()(_Iterator1 __it1, _Iterator2 __it2) const 
     { return *__it1 < *__it2; } 
    }; 

。 アイデアはありますか?

答えて

3

は、根本的な問題が何であるかを確実に知るませんが、これは間違いなく間違っている:

it &operator+(std::size_t n) { 
     i += n; 
     return *this; 
    } 

は、オペレータが新しいイテレータを返す必要があること、そしてそれが呼ばれています1を変更できません。これがない参照することにより、値反復子を返すこと

it operator+(std::size_t n) { 
     it temp = *this; 
     temp.i += n; 
     return temp; 
    } 

注:このような何か。

operator-と同じです。

+0

私は愚かな感じてわかりました... どうもありがとう:) –

+0

は愚かな感じることはありません。イテレータで迷子になるのは簡単です。 –

+0

私は良いプロトタイプ演算子+ ^^を使用しなかったので、もっとです。しかし、はいイテレータはあまり簡単ではない –

2

operator+のセマンティクスはoperator+=であり、operator-のセマンティクスはoperator-=です。イテレータを変更するべきではなく、変更された値を持つ新しいイテレータを作成して返します。また、署名付きの値を受け入れる必要があります。実際には、適切なランダムアクセスイテレータは両方の演算子のセットを持つ必要があるので、関数をそのまま保ちながらシグネチャを変更してください。

it& operator+=(difference_type n) { 
    i += n; 
    return *this; 
} 

it &operator-=(difference_type n) { 
    i -= n; 
    return *this; 
} 

次に、あなたはそれらの面でoperator+operator-を実装することができます。 (値によって、これらのリターンは、参照しないことに注意してください、とのconstをマークされている)

it operator+(difference_type n) const { 
    it result = *this; 
    result += n; 
    return result; 
} 

it operator-(difference_type n) const { 
    it result = *this; 
    result -= n; 
    return result; 
} 
+0

詳細をありがとう:) –

関連する問題