52

Is it possible to forward declare an standard container in a header file? For example, take the following code:

#include <vector>

class Foo
{
private:
    std::vector<int> container_;
    ...
};

I want to be able to do something like this:

namespace std
{
    template <typename T> class vector;
}

class Foo
{
private:
    std::vector<int> container_;
    ...
};

Can this be done?

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
Rob
  • 76,700
  • 56
  • 158
  • 197

3 Answers3

37

Declaring vector in the std namespace is undefined behavior. So, your code might work, but it also might not, and the compiler is under no obligation to tell you when your attempt won't work. That's a gamble, and I don't know that avoiding the inclusion of a standard C++ header is worth that.

See the following comp.std.c++.moderated discussion:

forward declaring std::vector. Works, but is it legal and standard compliant?

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • 1
    I followed your link to the discussion, but the people do not seem to be coming to an conclusion. Apparently, the stl implementation must not add any template parameters to the standard containers. hence, it should be allowed to forward declare the template. – Haplo Sep 17 '10 at 12:54
  • 1
    It's undefined, @Haplo. If the implementation *you're* using chooses to define the behavior beyond what the standard says, that's great, but it's still undefined, so your code won't be portable. The conclusion (judging from statements left unchallenged) is that the standard should allow it, but doesn't, and that there are two workarounds: Wrap the standard types in forward-declared user structs, or just bite the bullet and include the standard header. The latter is easy to do. – Rob Kennedy Sep 17 '10 at 13:30
  • 1
    "Statements left unchallenged" on Usenet are hardly an authoritative source. But, Jerry Coffin is right when he quotes [namespace.std]/1. In practice, if your compiler diagnoses `namespace std` declarations in non-system headers, or if your standard library is not implemented in C++, then you could have a problem, but those things never happen – Potatoswatter Jan 07 '15 at 13:33
18

I don't think so because the compiler would have no way of knowing how much space to allocate for the container_ object. At best you could do:

std::vector<int> *container_;

and new it in the constructor, since the compiler knows the size of a pointer.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • exactly what I just wanted to say – Paul Kapustin Nov 21 '08 at 00:01
  • 7
    Right, but that's a problem with all forward-declarations, not specifc to those in `namespace std`. So it answers the _real_ question, not the one OP asked. :P We simply cannot forward-declare something and then instantiate it by value, for obvious reasons. – underscore_d Jun 02 '17 at 19:20
12

Apart from what the others said, you may find it useful to know that there is a sanctioned way of forward-declaring iostreams and some related templates: The header <iosfwd>. It would be useful if the standard had more such headers.

Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130