1

In continuation to my question here:

I know that after a forward deceleration such as

class Foo;

I can declare a variable as Foo* or Foo&, but not Foo, and if I have a templated class Bar<T> that only has T* and T& inside it then the same rule would apply to Bar<Foo> (i.e. I would only need a forward deceleration in order to write Bar<Foo>).

My question is whether the STL class guarantee such a thing, that they only contain references and pointers to the template type. I tested this:

class A;
std::vector<A> b;

with the VS2010 implementation of the STL and it compiled, but I don't know if this is true for all STL containers, nor if this is just the way the MS implementation of the STL is or if it is part of the standard.

Community
  • 1
  • 1
Baruch
  • 20,590
  • 28
  • 126
  • 201

2 Answers2

3

The C++ standard requires complete types for all but a few class templates (e.g. std::shared_ptr, and std::unique_ptr in some special circumstances). The containers require full types, so your code sample would techincally yield undefined behaviour, even though it might work on some implementations.

Note that boost.container has std c++-like containers for incomplete types.

See this related SO post.

This is laid out in 17.6.4.8 [res.on.functions], where it specifies undefined behaviour

if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.

Thanks to @DietmarKühl for finding the appropriate quote.

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Even if the instantiations are merely declared? – Dietmar Kühl Jan 08 '14 at 22:18
  • @DietmarKühl I am not sure what the standard says about that. It may be technically UB, although unlikely to manifest itself in any nefarious way. But that is speculation. – juanchopanza Jan 08 '14 at 22:20
  • `vector` (at least in VS2010) does *not* require a full type, as I demonstrated myself in the question, so this must be at least somewhat inaccurate. – Baruch Jan 08 '14 at 22:20
  • 2
    @baruch It is UB as per the C++ standard. I said it *might* work on some implementations. Every now and then there is talk about lifting some of these restrictions. – juanchopanza Jan 08 '14 at 22:21
  • I think UB is a little harsh of the standard. If it compiles I see no reason it should not work as expected. All that is undefined is whether or not it compiles, which is not exactly *behavior*. But I am nitpicking. – Baruch Jan 08 '14 at 22:30
  • @baruch: No offense, but it sounds like you do not know what "undefined behavior" actually means. I suggest trying a search on Google or SO. – Nemo Jan 08 '14 at 22:57
  • @DietmarKühl Thanks, I added part of that clause. – juanchopanza Jan 09 '14 at 07:28
2

In 17.6.4.8 [res.on.functions] paragraph 2 it is stated

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.

That is, the standard library containers would need to make an explicit exemption allowing their instantiation for certain types with an incomplete type. I'm pretty that there is no such exception stated in the containers section.

Community
  • 1
  • 1
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380