Is an iterator a container with an incomplete data type legal?

Is the following code legal?

class A { std::map<int, A>::iterator x; }; 

Visual Studio 2015 accepts this, but clang says

 .../ndk/sources/cxx-stl/llvm-libc++/libcxx/include/utility:254:9: error: field has incomplete type 'A' _T2 second; ^ .... a.cpp:52:21: note: definition of 'A' is not complete until the closing '}' struct A ^ 

Edit:
The problem seems to be related to the standard library, http://rextester.com/QNNEG57036 does not work on it

My question is whether the law is legal or not, and not how to fix it (for example, changing the compiler flags).

+6
source share
1 answer

Unless the standard explicitly states that incomplete types are legal, they are not legal. The specific section is 17.6.4.8 [res.on.functions], paragraph 2:

In particular, the effects are undefined in the following cases:

[...]

  • if the incomplete type (3.9) is used as a template argument when creating an instance of the template component, unless this is specifically permitted for this component.

I do not think that any container is required to support incomplete types. Some of the smart pointers allow incomplete types. Out of my hands, I can't think of anything else that would allow incomplete types. A quick search for "incomplete" results in the following components that allow incomplete types as template arguments:

  • std::declval<T>()
  • std::unique_ptr<T>
  • std::default_delete<T>
  • std::shared_ptr<T>
  • std::weak_ptr<T>
  • std::enable_shared_from_this<T>

In the sample code, std::map<int, A>::iterator creates an instance of the template with an incomplete type. As a result, the code leads to undefined behavior.

+4
source

All Articles