Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaration of a typedef in C++

People also ask

Can I forward declare a typedef?

But you can't forward declare a typedef. Instead you have to redeclare the whole thing like so: typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; Ah, but I don't have any of those classes declared either.

What is forward declaration in C?

In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

What is forward declaration of a function?

A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier. In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function's body.

Can we typedef in declaring structure?

In C++, declaring a struct or class type does allow you to use it in variable declarations, you don't need a typedef . typedef is still useful in C++ for other complex type constructs, such as function pointers.


You can do forward typedef. But to do

typedef A B;

you must first forward declare A:

class A;

typedef A B;

For those of you like me, who are looking to forward declare a C-style struct that was defined using typedef, in some c++ code, I have found a solution that goes as follows...

// a.h
 typedef struct _bah {
    int a;
    int b;
 } bah;

// b.h
 struct _bah;
 typedef _bah bah;

 class foo {
   foo(bah * b);
   foo(bah b);
   bah * mBah;
 };

// b.cpp
 #include "b.h"
 #include "a.h"

 foo::foo(bah * b) {
   mBah = b;
 }

 foo::foo(bah b) {
   mBah = &b;
 }

To "fwd declare a typedef" you need to fwd declare a class or a struct and then you can typedef declared type. Multiple identical typedefs are acceptable by compiler.

long form:

class MyClass;
typedef MyClass myclass_t;

short form:

typedef class MyClass myclass_t;

In C++ (but not plain C), it's perfectly legal to typedef a type twice, so long as both definitions are completely identical:

// foo.h
struct A{};
typedef A *PA;

// bar.h
struct A;  // forward declare A
typedef A *PA;
void func(PA x);

// baz.cc
#include "bar.h"
#include "foo.h"
// We've now included the definition for PA twice, but it's ok since they're the same
...
A x;
func(&x);

Because to declare a type, its size needs to be known. You can forward declare a pointer to the type, or typedef a pointer to the type.

If you really want to, you can use the pimpl idiom to keep the includes down. But if you want to use a type, rather than a pointer, the compiler has to know its size.

Edit: j_random_hacker adds an important qualification to this answer, basically that the size needs to be know to use the type, but a forward declaration can be made if we only need to know the type exists, in order to create pointers or references to the type. Since the OP didn't show code, but complained it wouldn't compile, I assumed (probably correctly) that the OP was trying to use the type, not just refer to it.


Using forward declarations instead of a full #includes is possible only when you are not intending on using the type itself (in this file's scope) but a pointer or reference to it.

To use the type itself, the compiler must know its size - hence its full declaration must be seen - hence a full #include is needed.

However, the size of a pointer or reference is known to the compiler, regardless of the size of the pointee, so a forward declaration is sufficient - it declares a type identifier name.

Interestingly, when using pointer or reference to class or struct types, the compiler can handle incomplete types saving you the need to forward declare the pointee types as well:

// header.h

// Look Ma! No forward declarations!
typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere
typedef class A& ARef;

typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere
typedef struct B& BRef;

// Using the name without the class/struct specifier requires fwd. decl. the type itself.    
class C;         // fwd. decl. type
typedef C* CPtr; // no class/struct specifier 
typedef C& CRef; // no class/struct specifier 

struct D;        // fwd. decl. type
typedef D* DPtr; // no class/struct specifier 
typedef D& DRef; // no class/struct specifier