Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is iterator to a container with incomplete data type legal?

Is the following code legal?

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

Visual Studio 2015 accepts it, 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 with the standard library, http://rextester.com/QNNEG57036 fails on it

My question is whether the code is legal or not, not how to fix it (ex. by changing compiler flags).

like image 966
Dani Avatar asked Jun 11 '16 19:06

Dani


1 Answers

Unless explicitly stated in the standard 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 an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.

I don't think any of containers is required to support incomplete types. Some of the smart pointers do allow incomplete types. Off-hand I can't think of anything else which would allow incomplete types. A quick search for "incomplete" yields the following components allowing 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 code example, std::map<int, A>::iterator instantiates a template with an incomplete type. As a result the code results in undefined behavior.

like image 115
Dietmar Kühl Avatar answered Oct 15 '22 08:10

Dietmar Kühl