2

私はこれに困惑しています...コンパイラの出力:

d:\data\personal\projects\test\test.cpp(42): エラー C2105: '--' には左辺値が必要です

#include <iostream>
#include <algorithm>
#include <iterator>

class FOO
{
public:
    typedef int* iterator;
    typedef const int* const_iterator;

    class explicit_iterator : public std::iterator< std::bidirectional_iterator_tag, int >
    {
    public:
        explicit_iterator(int* ptr = nullptr) : m_ptr(ptr) {}
        bool operator ==(const explicit_iterator& rhs) const { return m_ptr == rhs.m_ptr; }
        bool operator !=(const explicit_iterator& rhs) const { return m_ptr != rhs.m_ptr; }

        reference operator *() const { return *m_ptr; }

        explicit_iterator& operator ++() { ++m_ptr; return *this; }
        explicit_iterator& operator --() { --m_ptr; return *this; }

    private:
        int* m_ptr;
    };

    FOO(int val = 0) { std::fill( begin(), end(), val ); }

    iterator begin() { return m_data; }
    iterator end() { return m_data + 10; }

    explicit_iterator begin2() { return explicit_iterator( begin() ); }
    explicit_iterator end2() { return explicit_iterator( end() ); }

private:
    int m_data[10];
};

int main (int, char *[])
{
    FOO foo;
    // This is the line that fails!  (Not this one, the one right below!!!)
    std::copy( foo.begin(), --foo.end(), std::ostream_iterator<int>( std::cout, "\n" ) ); // C2105

    // All these variants are good
    std::copy( foo.begin2(), --foo.end2(), std::ostream_iterator<int>( std::cout, "\n" ) ); // good
    std::copy( foo.begin(), foo.end() - 1, std::ostream_iterator<int>( std::cout, "\n" ) ); // good
    int* end = foo.end();
    std::copy( foo.begin(), --end, std::ostream_iterator<int>( std::cout, "\n" ) ); // good

    return 0;
}
4

3 に答える 3

4

右辺値またはポインター型を事前デクリメントすることはできません。呼び出しfoo.end()は右辺値int*を返し、それを事前にインクリメント/事前デクリメントすることはできません。

--foo.end2()この場合、プレインクリメントはメンバー関数であり、右辺値でメンバー関数を呼び出すことは言語で合法であるため、次の呼び出しは機能します。構文はより明示的なものと同等であり、理解しやすくなっています。

foo.end2().operator--();
于 2013-10-31T20:07:52.370 に答える
0

このステートメントは無効です。

std::copy( foo.begin(), --foo.end(), std::ostream_iterator( std::cout, "\n" ) ); // C2105

関数 foo.end() は、演算子 -- を適用できない一時オブジェクトを返します。

于 2013-10-31T20:10:39.673 に答える
0

pre-decrement のオペランドは、組み込み型 (ポインターなど) の変更可能な左辺値でなければなりません。C++11 5.3.2「インクリメントとデクリメント」を参照してください。

メンバー関数はFOO::end()、変更可能な左辺値ではなく右辺値である組み込み型 (ポインター) を返すため、プレデクリメント演算子は使用できません。

FOO::end2()右辺値を返しますが、組み込み型ではありません。したがって、オーバーロードされたプレデクリメント演算子を呼び出すことができます。

そして最後に--end、変更可能な左辺値に作用しています。

于 2013-10-31T20:19:57.800 に答える