Forward Declare a Standard Container

Forward declare a standard container?

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?

Forward declaration of objects with STL containers

The relevant rules for the standard library types are in [res.on.functions]:

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.

This:

vector<A> Av;

is fine. std::vector is allowed to be instantiated with an incomplete type, as long as it becomes complete before you use any of the members. There is an explicit exception for this in the standard in [vector.overview]:

An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness
requirements 17.6.3.5.1. T shall be complete before any member of the resulting specialization of vector
is referenced.

There is similar wording for std::list and std::forward_list.

This:

map<int, A> Am;

is ill-formed. std::map requires a complete type at point of instantiation as per the first quote. There is no exception for this container in the way that there is for vector.

This:

pair<int, A> Ap;

cannot possibly ever work, since pair is just a simply struct with two members. In order to have a member of type A, you need a complete type.

Why can't a forward declaration be used for a std::vector?

The compiler needs to know how big "B" is before it can generate the appropriate layout information. If instead, you said std::vector<B*>, then the compiler wouldn't need to know how big B is because it knows how big a pointer is.

Declaration of std::vector works with forward declared classes?

This is an interesting topic (at least to me) and applies to other std containers.

Originally the standard made it undefined behaviour to instantiate a container of an incomplete type. However implementations did not disallow it. This was in all likelihood not deliberate, but merely a side-effect of the fact that elements in (for example the vector) are stored in a memory location that is referenced by a pointer.

Thus the size of an element does not need to be known until an element is actually required - during the instantiation of a member function of the vector.

Here is a starting point for research if you'd like to explore further:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4056.html

How to forward declare a class under a namespace in c++, such as std::string?

std::string is a typedef so you cannot just forward declare it. You could look up the exact declaration, forward declare that and define the typedef yourself, but then you'd also have to forward declare char_traits and allocator. So this should might work, although it's not supposed to*:

namespace std
{
template< class T, class Traits, class Allocator >
class basic_string;

template< class T >
struct char_traits;

template< class T >
class allocator;

typedef basic_string< char, char_traits< char >, allocator< char > > string;
}

but in the end you're probably better off including . I'm also unsure whether these declarations are exactly the same on all platforms, not to mention the problems it would cause should the declaration in the string header ever change.

*see comment below

Forward declaring the mapped type of a map and C++11

According to the requirements in 17.6.4.8 [res.on.functions] paragraph 2 it states:

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.

Few components explicitly state that template arguments are allowed to be incomplete. That, is you are making an assumption which is not covered by the standard.



Related Topics



Leave a reply



Submit