1
votes

GCC can compile the code below but VS2010 express couldn't:

#include <iostream>
#include <queue>
using namespace std;

struct A
{
  deque<A>::iterator next;
};
int main()
{
  A a;
}

Error message:

error C2027: use of undefined type 'A' main.cpp(6) : see declaration of 'A' main.cpp(7) : see reference to class template instantiation 'std::deque<_Ty>' being compiled 1> with 1> [ 1> _Ty=A 1> ]

Is there any way to solve this problem except using pointers?

1
Which is the error message?marom
error C2027: use of undefined type 'A' main.cpp(6) : see declaration of 'A' main.cpp(7) : see reference to class template instantiation 'std::deque<_Ty>' being compiled 1> with 1> [ 1> _Ty=A 1> ]Anton Agapov
Does this actually run with GCC?Bathsheba
Interestingly, std::unique_ptr<A> next; works on MSVC2012 as the struct member. Perhaps something to do with how the standard library is implemented. I wonder if the standard insists that the construct is valid in this case, and perhaps not in your case.Bathsheba
The C++ standard requires the type to be complete to instantiate standard containers (otherwise undefined behaviour, no diagnostic required). So you may not use std::deque<A> inside the definition of A, even if you forward-declare it. As you can't name the iterator type of std::deque<A> without instantiating it, I'm afraid this design will not work.Michael Karcher

1 Answers

1
votes

As discussed for example in How come I can use a forward-declared class in a std::vector?, instantiating standard containers with incomplete types is undefined behaviour. To be able to access the iterator type of std::deque<A>, it is required to instantiate this class, so the program you give has undefined behaviour. In this specific instance, in gcc undefined behaviour happens to be what you expect, while Visual Studio (with its Dinkumware Standard Library implementation) happens to fail to compile. It is likely that Visual Studio behaves different in Debug and Release mode, as in debug mode, the containers (and iterators) are much more complex to be able to check for many iterator abuses.

I was unable to quickly find a reference that declaring a pointer to an deque iterator where the element type is an incomplete type is allowed, and I am afraid that most likely replacing the iterator by an pointer to an iterator does not make this program defined (although it might make it work in more environments). If you were to replace the iterator by a pointer: This will surely work. I can't tell you whether it's the only solution, as you didn't clearly state what problem you try to solve. Possibly there is a different design approach to your problem that doesn't require this member variable.