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>
...
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;
};
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;
}
Related
I have created a template class A<T> in mynamespace which I need to forward declare to use in class B in mynamespace2. Is it possible to forward declare a specific instance of A for use in B, namely A<int>?
File: a.h
#include "b.h"
namespace mynamespace{
template <class T>
class A{
A(T); // constructor
mynamespace2::B* b_attribute;
};
}
File: b.h
/* How to forward declare A<int>? This doesn't work:
*
* namespace mynamespace{
* class A<int>;
* }
*
* neither does this:
*
* namespace mynamespace{
* template <class T>
* class A<T>
* }
*/
namespace mynamespace2{
class B{
B();
mynamespace::A<int>* a_attribute; // for use over here
virtual void f(A<int>*); // note: virtual function
};
}
I appreciate any help.
This is no different than forward-declaring anything else, except that you have to get the namespace right:
namespace mynamespace{
template <class T> class A;
}
A is declared in mynamespace, so you have to specify it, as such.
If you really want to avoid explicitly specifying the namespace every time, add a using declaration:
namespace mynamespace2{
using mynamespace::A;
class B{
B();
A<int>* a_attribute; // for use over here
};
}
Once a using declaration is made, you can just refer to A anywhere within mynamespace2.
Note that you must still forward-declare the template in the other namespace, before pulling it in with using.
I looked around and tried to find an answer to this. Is it possible to define the member functions of a template class in a namespace within a cpp file? I get an error when I try to do it.
Here are the two files I am trying to compile.
ArrayList.hpp
template<typename T>
class ArrayList{
ArrayList();
~ArrayList();
}
ArrayList.cpp
#include "ArrayList.hpp"
namespace{
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
Compiler error
error: cannot define or
redeclare 'ArrayList<T>' here because namespace '' does not enclose
namespace 'ArrayList'
ArrayList<T>::ArrayList()
You need to declare your class in the same namespace as you define its member functions.
And you are missing a template<typename T> before your destructor.
namespace ANamespace
{
template<typename T>
class ArrayList
{
ArrayList();
~ArrayList();
};
template<typename T>
ArrayList<T>::ArrayList()
{
/* function body goes here */
}
template<typename T>
ArrayList<T>::~ArrayList()
{
/* function body goes here */
}
}
Is it possible to define the member functions of a template class in a namespace within a cpp file?
No, that's not possible. As with any other class declarations the member function declarations and their definitions must appear in the same namespace.
Also unnamed namespaces as used in your example will be seen only in that particular translation unit.
You generally can't put template definitions to separate translation units (unless you have particular specialization cases). Read more about this here please:
Why can templates only be implemented in the header file?
How to fix it?
Just move everything out to your header file and drop the unnamed namespace like this:
ArrayList.hpp
template<typename T>
class ArrayList{
ArrayList();
~ArrayList();
}; // Semicolon at end of class declaration is essential
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
template<typename T> // <<<<< Repeat for evey function definition
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
If you really want to have a namespace, just provide a named one and enclose everything from above (still in the header):
namespace MyUtilities {
template<typename T>
class ArrayList{
public: // <<<<<< Allow access to these functions
ArrayList();
~ArrayList();
};
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
template<typename T>
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
}
See the fully working example here please.
Also to make that stuff usable use the public keyword as shown above.
Firstly you cannot define a template class's methods in a .cpp file. You need to define template class methods in the header file itself (or in another file and then import that via preprocessor includes in the header file itself) For more see Why can templates only be implemented in the header file?
Anonymous namespaces namespace { are used to define things that have internal linkage, i.e. similar to the effect static has on functions defined in implementation files. Read this for more information Why are unnamed namespaces used and what are their benefits?
But in your case you want to define the class methods to be externally visible because you have them declared publicly in the header file. So you probably don't want to have those definitions be in an anonymous namespace.
If you have a namespace enclosing your class in your header file, for example namespace array_list then you should just define your class methods in that same namespace in the header file itself since it's a template class and needs to be visible wherever used.
I've a question about something what really confuses me!
Let's watch this code righ here:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
class example;
class anything_else;
class A {
public:
A();
};
...
What does class example; and class anything_else; mean,
while class A {}; gets declared? Inside the CPP File i saw definitions like void example::release() { ... } and so on...
I'm really confused, does anyone have a example with class example; ... ?
What does class example; and class anything_else; mean
They are declarations of the classes example and anything_else. They tell the compiler that those are valid class names. This kind of declaration is informally referred to as "forward declaration".
while class A {}; gets declared?
class A gets defined.
Inside the CPP File i saw definitions like void example::release() { ... } and so on...
That's the definition of the function example::release.
Somewhere in the definition of example, there's the declaration of the function:
class example
{
// ...
void release(); // declaration
};
If example is only declared and not defined, then the definition of example::release results in a compilation error.
if you want to have member variables of a type that have not yet been included you do a forward declaration of the type.
class X;
forward declares the class X so you can have a. e.g. a pointer to that class in our class declaration.
class Y
{
...
X* p;
};
later you must supply the definition of the class somewhere in your .cpp file.
This question already has answers here:
Forward declaration of nested types/classes in C++
(7 answers)
Closed 2 years ago.
I have a class like so...
class Container {
public:
class Iterator {
...
};
...
};
Elsewhere, I want to pass a Container::Iterator by reference, but I don't want to include the header file. If I try to forward declare the class, I get compile errors.
class Container::Iterator;
class Foo {
void Read(Container::Iterator& it);
};
Compiling the above code gives...
test.h:3: error: ‘Iterator’ in class ‘Container’ does not name a type
test.h:5: error: variable or field ‘Foo’ declared void
test.h:5: error: incomplete type ‘Container’ used in nested name specifier
test.h:5: error: ‘it’ was not declared in this scope
How can I forward declare this class so I don't have to include the header file that declares the Iterator class?
This is simply not possible. You cannot forward declare a nested structure outside the container. You can only forward declare it within the container.
You'll need to do one of the following
Make the class non-nested
Change your declaration order so that the nested class is fully defined first
Create a common base class that can be both used in the function and implemented by the nested class.
I don't believe forward declaring inner class of on an incomplete class works (because without the class definition, there is no way of knowing if there actually is an inner class). So you'll have to include the definition of Container, with a forward declared inner class:
class Container {
public:
class Iterator;
};
Then in a separate header, implement Container::Iterator:
class Container::Iterator {
};
Then #include only the container header (or not worry about forward declaring and just include both)
I know of no way to do exactly what you want, but here is a workaround, if you are willing to use templates:
// Foo.h
struct Foo
{
export template<class T> void Read(T it);
};
// Foo.cpp
#include "Foo.h"
#include "Container.h"
/*
struct Container
{
struct Inner { };
};
*/
export template<>
void Foo::Read<Container::Inner>(Container::Inner& it)
{
}
#include "Foo.h"
int main()
{
Foo f;
Container::Inner i;
f.Read(i); // ok
f.Read(3); // error
}
Hopefully, this idiom might be of some use to you (and hopefully your compiler is EDG-based and implements export ;) ).
I'm using the CRTP pattern to create an interface, which other classes will derive from.
In the interface I forward declare a structure (important because I don't want to drag other stuff in the interface), but I include its definition in the cpp file which defines the interface.
Interface.h
#ifndef INTERFACE_H_INCLUDED
#define INTERFACE_H_INCLUDED
// forward declaration
class ForwardDecl;
template <class Derived>
class Interface
{
public:
ForwardDecl interfaceMethod();
};
#endif // INTERFACE_H_INCLUDED
ForwardDecl.h
#ifndef FORWARDDECL_H_INCLUDED
#define FORWARDDECL_H_INCLUDED
struct ForwardDecl
{
ForwardDecl(int i):internal(i)
{}
int internal;
};
#endif // FORWARDDECL_H_INCLUDED
Interface.cpp
#include "Interface.h"
#include "ForwardDecl.h"
template<class Derived>
ForwardDecl Interface<Derived>::interfaceMethod()
{
return static_cast<Derived *>(this)->implementation_func();
}
And this is the implementation which implements the interface
Implementation.h
#ifndef IMPLEMENTATION_H_INCLUDED
#define IMPLEMENTATION_H_INCLUDED
#include "Interface.h"
class ForwardDecl;
class Implementation: public Interface<Implementation>
{
friend class Interface<Implementation>;
private:
ForwardDecl implementation_func();
};
#endif // IMPLEMENTATION_H_INCLUDED
Implementation.cpp
#include "Implementation.h"
#include "ForwardDecl.h"
#include <iostream>
struct ForwardDecl Implementation::implementation_func()
{
ForwardDecl fd(42);
std::cout << fd.internal << std::endl;
return fd;
}
And the main file
#include <iostream>
#include "Implementation.h"
#include "ForwardDecl.h"
using namespace std;
int main()
{
Implementation impl;
ForwardDecl fd = impl.interfaceMethod();
cout << fd.internal << endl;
return 0;
}
I get linking errors on both VS and GCC.
Any workaround? Thank you.
There is a flaw in your very approach: You have a public function returning a ForwardDecl instance, so every client wanting to use this function also must include the according definition of that type, which implies you can make that type public from the beginning. This includes making the function definition inline, which will fix your linker problems.
However, if you really want to hide the content of that structure and you are sure clients don't need it directly, you can declare it and then pass around references to such a structure (or pointers, but raw pointers are evil albeit not in the same league of evil as #macros). In that case, I would still make the function definition inline.
If you really, really want to not make the function inline, you can also explicitly instantiate the function template for the types that you need. You would add at the end of the template's .cpp file something like template class Interface<int>; (I don't remember the exact syntax so take that with a few flakes of fleur de sel, check out the C++ FAQ at parashift.com for more info). This makes the template a little less universal though, as it requires adjustments for any type that you want to use it with, but it can be an approach in some corner cases.
The definitions of function templates and member functions of class templates need to be visible in all translation units that instantiate those templates. That is, you shouldn't put template definitions in a .cpp file, which means you need to move the contents of Interface.cpp up into Interface.h.