4

画像内のピクセルを水平または垂直に移動するための独自の作業イテレータがありました。テンプレートパラメータを介して、そうである場合とそうでない場合があります( Dr. Dobb's の巧妙constなトリック)。

それから、std::iterator基底クラスがあることに気づき、自分のものをもっとSTLlyにして、それを継承することにしました。

残念ながら、Visual Studio 2012 (バージョン 11.0.60315.01 Update 2) ではコンパイルできなくなりました。私は実際にコンパイラーのスタックオーバーフローを取得することができました。これはメッセージです:

エラー 1 エラー C1063: コンパイラの制限: コンパイラ スタック オーバーフロー d:\…\source.cpp 42 1 ConsoleApplication3

私のクラスの非常に簡素化されたバージョンは次のようになります。

#include <iterator>

// This comes from the outer image class.
typedef float color_type;

template<bool IS_CONST = false>
struct Iterator : public std::iterator<std::random_access_iterator_tag, color_type>
{
    // This is myself...
    typedef Iterator<IS_CONST> iterator;
    // ... and my variants.
    typedef Iterator<true> const_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator;
    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

    // Make base class typedefs available.
    typedef typename iterator::value_type value_type;
    typedef typename iterator::difference_type difference_type;

    // My own typedefs to deal with immutability.
    typedef value_type const & const_reference;
    typedef typename std::conditional<IS_CONST, const_reference, typename iterator::reference>::type reference;

    Iterator()
        : _position(nullptr),
        _step()
    {
    }

    Iterator(value_type * const position, difference_type const step)
        : _position(position),
        _step(step)
    {
    }

    iterator const operator-(difference_type n) const
    {
        return iterator(*this) -= n;
    }

    difference_type operator-(iterator const rhs) const
    {
        assert(_step == rhs._step);
        return (_position - rhs._position) / _step;
    }

protected:
    value_type * _position;
    difference_type _step;
};

int main()
{
    float a = 3.141f;
    // Instanciate all variants.
    Iterator<false> empty;
    Iterator<true> const_empty;
    Iterator<false> some(&a, 5);
    Iterator<true> const_some(&a, 5);
    return 0;
}

2 つのうちのいずれかを削除operator-すると、コンパイラーは満足します。

ここで何が問題なのか、誰かが私に説明できますか? または、修正を提供する方がよいでしょうか?

ありがとう


更新:ところで、GCC 4.7.2 は問題なくコンパイルできます。

4

2 に答える 2

3

最小限の例:

template<bool B>
struct Iterator
{
    typedef typename Iterator<B>::some_type some_type ;

    int foo();

    int foo(some_type n);
};

int main()
{
    return 0;
}

http://rise4fun.com/Vcpp/2eQからの出力:

testvc.cpp(1): 情報: CompilerVersion ヒントが見つかりませんでした。デフォルトのコンパイラ バージョン 'VS2012CTP' を使用しています
testvc.cpp(1) : 情報: Visual C++ コンパイラのこのオンライン バージョンでは使用できないディレクティブ '#include' を無視します
testvc.cpp(1) : info : このオンライン バージョンの Visual C++ コンパイラに一致する標準ライブラリ ヘッダーを自動的にインポートしています
Microsoft (R) C/C++ 最適化コンパイラ バージョン 17.00.51025 for x86
Copyright (C) Microsoft Corporation. 全著作権所有。

testvc.cpp
--\testvc.cpp(10): 致命的なエラー C1063: コンパイラの制限: コンパイラのスタック オーバーフロー
        --\testvc.cpp(11) : コンパイル中のクラス テンプレートのインスタンス化 'Iterator' への参照を参照してください
の内部コンパイラ エラー。後で Microsoft にエラー レポートを送信するように求められます。

これを解決するには、コードから次の行を削除します。

// Make base class typedefs available.
typedef typename iterator::value_type value_type;
typedef typename iterator::difference_type difference_type;

次に、Visual C++ ( http://rise4fun.com/Vcpp/1pg )でコンパイルします。

testvc.cpp(1): 情報: CompilerVersion ヒントが見つかりませんでした。デフォルトのコンパイラ バージョン 'VS2012CTP' を使用しています
testvc.cpp(1) : 情報: Visual C++ コンパイラのこのオンライン バージョンでは使用できないディレクティブ '#include' を無視します
testvc.cpp(1) : info : このオンライン バージョンの Visual C++ コンパイラに一致する標準ライブラリ ヘッダーを自動的にインポートしています
testvc.cpp(2) : 情報: Visual C++ コンパイラのこのオンライン バージョンでは使用できないディレクティブ '#include' を無視します
Microsoft (R) C/C++ 最適化コンパイラ バージョン 17.00.51025 for x86
Copyright (C) Microsoft Corporation. 全著作権所有。

testvc.cpp
testvc.cpp(64) : 情報 : エラーなしでコンパイルされたファイル!

GCC ( http://ideone.com/mEX18H )で期待どおりに動作します。

結果: 成功時間: 0 秒 メモリ: 2896 kB 戻り値: 0
入力: いいえ

出力:
0 0
于 2013-05-22T19:52:27.267 に答える
1

ああ、それはばかだった…ジェリーの答えをいじっていると、自分の間違いを見つけることができました。もちろん、コンパイラは再帰に入り、スタックオーバーフローにつながります。私が書いたとき

// Make base class typedefs available.
typedef typename iterator::value_type value_type;
typedef typename iterator::difference_type difference_type;

私の意図は、基本クラスをtypedef簡単に利用できるようにすることでした。iteratorしかし、資格なしで書くことは、typedef上記の私の他のおかげで、クラス自体を指します。

// This is myself...
typedef Iterator<IS_CONST> iterator;

iteratorしたがって、 inを正しく参照することでstd、問題は解決、自分typedefの s を維持できます。

// Make base class typedefs available.
typedef std::iterator<std::random_access_iterator_tag, color_type> base_class;
typedef typename base_class::value_type value_type;
typedef typename base_class::difference_type difference_type;

興味深いことに、GCC には問題がないようです。

于 2013-05-23T08:53:46.067 に答える