gmkforever
gmkforever

Reputation: 13

How do you forward declare header files?

I'm trying to forward declare the header files #include<memory_resource> and #include<deque>. But the following doesn't seem to work. This is pseudo-code:

A.hpp

class memory_resource;
class deque;

class A
{
public:
    ...

private:
    std::pmr::deque<index_t> tempQueue;
}

A.cpp

#include<memory_resource>
#include<deque>

...

Upvotes: 1

Views: 825

Answers (2)

Ranoiaetep
Ranoiaetep

Reputation: 6637

For a rule of thumb, you should not forward declare anything from the standard library, unless the class specifically says it can be forward declared.

To use anything from the standard library, you must actually include them:

// A.hpp
#include <memory_resource>
#include <deque>

class A {
    std::pmr::deque<index_t> tempQueue;
}

Now, let's pretend you are not forward declaring anything from the standard library. You don't forward declare header files, instead you forward declare classes.

So if you have a class named deque defined in my_deque.cpp file, in another file, you might do:

// my_deque.cpp

class deque { /* some definitions ... */ };

// A.hpp

class deque;

You don't forward declare the file, my_deque, instead you forward declare the class deque .


Secondly, the deque class was actually located in a namespace. So in order to forward declare deque in another file, you must declare it within the same namespace:

// my_deque.cpp

namespace my_std::pmr{
    class deque { /* some definitions ... */ };
}

// A.hpp

namespace my_std::pmr{
    class deque;
}

Third, deque was actually a templated class, so to forward declare it, you must also declare it along all the template argument, including anything with default arguments:

// my_deque.cpp

namespace my_std::pmr{
    template<typename T, typename Allocator = std::allocator<T>>
    class deque { /* some definitions ... */ };
}

// A.hpp

namespace my_std::pmr{
    template<typename T, typename Allocator = std::allocator<T>>
    class deque;
}

Fourth, you cannot use a forward declared class as a class member directly. In order to create a class, you must be able to calculate the size of the class. To do that, you must also know the sizes of each class members. However, you can't know the size of a forward declared class, because you don't know what members does that class have, so you can't use a forward declared class as a class member.

However, you can use a pointer of a forward declared class as a class member, since all pointers have the same size:

// my_deque.cpp

namespace my_std::pmr{
    template<typename T, typename Allocator = std::allocator<T>>
    class deque { /* some definitions ... */ };
}

// A.hpp

namespace my_std::pmr{
    template<typename T, typename Allocator = std::allocator<T>>
    class deque;
}

class A{
    my_std::pmr::deque<index_t>* p_tempQueue;
}

Upvotes: 1

eerorika
eerorika

Reputation: 238301

No, you cannot "forward declare header files".

In order to define a member of a given type, that type must first be defined. You can achieve that by including the header that defines it.

Since you define the class A in A.hpp and that class has a member of type std::pmr::deque<index_t>, you must include the definition of std::pmr::deque into A.hpp, before the definition of the class A.

Here is a working example:

// A.hpp
#include <deque>
#include <memory_resource>
using index_t = int;
class A
{
    std::pmr::deque<index_t> tempQueue;
};

Upvotes: 3

Related Questions