anatolyg
anatolyg

Reputation: 28279

Forward declarations that involve std::vector, etc

I have used forward declarations a lot; they help avoid many #includes, improve compilation time and what not. But what if i want to forward-declare a class in the standard library?

// Prototype of my function - i don't want to include <vector> to declare it!
int DoStuff(const std::vector<int>& thingies);

I have heard it's forbidden/impossible to forward-declare std::vector. Now this answer to an unrelated question suggests to rewrite my code this way:

stuff.h

class VectorOfNumbers; // this class acts like std::vector<int>
int DoStuff(const VectorOfNumbers& thingies);

stuff.cpp

// Implementation, in some other file
#include <vector>
class VectorOfNumbers: public std::vector<int>
{
    // Define the constructors - annoying in C++03, easy in C++11
};

int DoStuff(const VectorOfNumbers& thingies)
{
    ...
}

Now, if i use VectorOfNumbers instead of std::vector<int> in all contexts throughout my project, everything is going to be good, and i don't need to #include <vector> in my header files anymore!

Does this technique have major disadvantages? Can the gain of being able to forward-declare vector outweigh them?

Upvotes: 2

Views: 1598

Answers (5)

idbrii
idbrii

Reputation: 11926

Instead of inheritance, you could use composition:

// Implementation, in some other file
#include <vector>
class VectorOfNumbers
{
    public:

    std::vector<int>& container;

    VectorOfNumbers(std::vector<int>& in_container)
        : container(in_container)
    {
    }
};

int DoStuff(const VectorOfNumbers& thingies)
{
    std::sort(thingies.container.begin(), thingies.container.end());
    // ...
}

The downside is the extra variable name on every access.

Also, you'd need this implementation to be in a header file included by cpps so they will know what they can do with VectorOfNumbers.

Essentially, just making a wrapper for your vector. This is like a light-weight version of PImpl (we only care about avoiding header dependencies so we don't need the full pointer decoupling). It avoids the issues raised by Mark B and ybungalobill.

But I don't think it's really worth it.

Upvotes: 0

Yakov Galka
Yakov Galka

Reputation: 72489

The reason I wouldn't do this:

const std::vector<int>& a = a_3rd_party_lib::get_data(); // this type is out of your control
DoStuff(a); // you cannot pass it to this function! 

Upvotes: 3

Mark Ransom
Mark Ransom

Reputation: 308276

This works well for the interface for a class, but not for the implementation. If your class has any vector members you must #include <vector> or the class definition will not compile.

Upvotes: 0

Mark B
Mark B

Reputation: 96271

If you ever delete a VectorOfNumbers as a std::vector<int> (and since you used public inheritance this conversion is implicit) you've entered the realm of undefined behavior. This is probably more likely to accidentally happen than one might suspect.

I've never personally noticed significant compilation slowdown from just including vector where needed, but if you really want to isolate the include, use a client API interface that doesn't know about the underlying container type (vector) and pimpl the vector include into a single source file.

Upvotes: 6

ObscureRobot
ObscureRobot

Reputation: 7336

You include <vector> in your header file. The <vector> header will have been built to prevent multiple inclusions, so you just include it everywhere you need it.

Upvotes: 0

Related Questions