primfaktor
primfaktor

Reputation: 2999

Why does the VC2012 compiler get into a stackoverflow (error C1063)?

I had my own working iterator to go over pixels in an image horizontally or vertically. Via template parameter, it could be const or not (neat trick from Dr. Dobb's).

Then I realized there is a std::iterator base class and I thought I'd make my stuff more STLly and inherit from it.

Unfortunately, now Visual Studio 2012 (Version 11.0.60315.01 Update 2) won't compile it anymore. I actually managed to get the compiler stackoverflow. This is the message:

Error 1 error C1063: compiler limit : compiler stack overflow d:\…\source.cpp 42 1 ConsoleApplication3

A very stripped down version of my class looks like this:

#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;
}

Removing either one of the two operator- makes the compiler happy.

Can somebody emplain to me what the problem is here? Or even better provide a fix for it?

Thanks


Update: Oh and by the way, GCC 4.7.2 happily compiles it.

Upvotes: 4

Views: 1060

Answers (2)

primfaktor
primfaktor

Reputation: 2999

Oh my, that was dumb… Playing with jerry's answer led me to find my mistake. Of course the compiler gets into recursion thus leading to a stackoverflow. When I wrote

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

my intention was to make the base class' typedefs easily available. But writing iterator without any qualification refers to the class itself, thanks to my other typedef above, duh!

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

So by correctly referring to the iterator in std, the problem is solved and I get to keep my typedefs.

// 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;

Interesting though, that GCC doesn't seem to have a problem with it.

Upvotes: 1

jerry
jerry

Reputation: 2611

Minimal example:

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

    int foo();

    int foo(some_type n);
};

int main()
{
    return 0;
}

Output from http://rise4fun.com/Vcpp/2eQ:

testvc.cpp(1) : info : Could not find CompilerVersion hint, using default compiler version 'VS2012CTP'
testvc.cpp(1) : info : Ignoring directive '#include', which cannot be used in this online version of the Visual C++ compiler
testvc.cpp(1) : info : Automatically importing the Standard Library headers which match this online version of the Visual C++ compiler
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51025 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

testvc.cpp
--\testvc.cpp(10) : fatal error C1063: compiler limit : compiler stack overflow
        --\testvc.cpp(11) : see reference to class template instantiation 'Iterator' being compiled
Internal Compiler Error in .  You will be prompted to send an error report to Microsoft later.

To solve it, remove the following lines from your code:

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

It then compiles in Visual C++ (http://rise4fun.com/Vcpp/1pg):

testvc.cpp(1) : info : Could not find CompilerVersion hint, using default compiler version 'VS2012CTP'
testvc.cpp(1) : info : Ignoring directive '#include', which cannot be used in this online version of the Visual C++ compiler
testvc.cpp(1) : info : Automatically importing the Standard Library headers which match this online version of the Visual C++ compiler
testvc.cpp(2) : info : Ignoring directive '#include', which cannot be used in this online version of the Visual C++ compiler
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51025 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

testvc.cpp
testvc.cpp(64) : info : File compiled with no errors!

and works as expected in GCC (http://ideone.com/mEX18H):

result: Success     time: 0s    memory: 2896 kB     returned value: 0 
input: no

output:
0 0

Upvotes: 3

Related Questions