Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I forward declare typedefs?

Tags:

c++

c++11

namespace O
{
    class A{};


    class A;   // ok
    typedef A K; // ok

    struct A;  // ok(C++11): A is a class but for references and pointer it have the same meaning
    class K;   // (1) error: K is a typedef (of a class...)
}

namespace U
{
    typedef O::A A;


    class A;      // (2) error: A is a typedef (of  a class...)
}

What is the reason(s) standard C++ don't allow these cases (1 & 2) to compile?

like image 212
Klaim Avatar asked Jan 21 '13 17:01

Klaim


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.

Can you forward declare a struct?

In C++, classes and structs can be forward-declared like this: class MyClass; struct MyStruct; In C++, classes can be forward-declared if you only need to use the pointer-to-that-class type (since all object pointers are the same size, and this is what the compiler cares about).

Can you forward declare a class C++?

In C++, Forward declarations are usually used for Classes. In this, the class is pre-defined before its use so that it can be called and used by other classes that are defined before this. Example: // Forward Declaration class A class A; // Definition of class A class A{ // Body };

Can you forward declare a namespace?

There is no forward declaration of namespace.


1 Answers

You are confused or your example doesn't show what you're asking about. In your example code you are not trying to "forward declare a typedef" (such as thing isn't possible or useful, see below) you are trying to redeclare an existing typedef-name (i.e. an alias for one type) as a completely different type.

You've already said K is a typedef for A, then you say it's a class K. Make your mind up. It's can't be both class A and class K. Both (1) and (2) fail for that same reason.

Going through these lines of the example:

class A;   // ok
typedef A K; // ok

Right so far.

struct A;  // ok(C++11): A is a class but for references and pointer it have the same meaning

I don't know why you've said "C++11" here, this is OK in C++03 too. Classes and structs are the same kind of thing in C++. They are both "object types" and both "class types". For a forward declaration the class-key (i.e. struct or class) is interchangeable.

class K;   // (1) error: K is a typedef (of a class...)

K has been declared as a typedef for class A, the name can't be reused for declaring a new type in the same scope.

[Aside: C does allow the following, because struct names and typedef names are in separate namespaces:

struct A { };
typedef struct A K;  // N.B. need "struct A" not just "A"
struct K { }; 

But now there are two different types called struct K and K, which are unrelated. Doing this would be confusing and pretty dumb.]

But from your comments maybe that's not what you're actually trying to do anyway.

Based on your comments maybe your broken examples are misleading and what you really want to do is:

typedef class A K;   // forward declare A as class and declare K as typedef for it

This declares a typedef, for a type which is not defined yet.

It would be useless to forward-declare a typedef, you couldn't do anything with it because you wouldn't know what kind of type it was a typedef for, and there is very little you can do in C++ without knowing something about a type. Without knowing if it's an object type, reference type or function type all you can realistically do is declare another typedef for it!

Consider:

typedef K;   // declares K to be a typedef

K* f();      // function returning pointer to K
void g(K*);  // function taking pointer to K

I think you're saying you want that to be valid, so do you expect this to work?

K* k = f();
g(k);

That should work, right? You don't need to know the type of K because you only pass around pointers to it, right? Wrong. What if you later define K like this:

typedef int& K;

Now f has the signature int&* f() which is invalid. You have to know what a typedef is a typedef for, so its declaration has to say what it is not just forward-declare it as a name.

like image 115
Jonathan Wakely Avatar answered Oct 06 '22 09:10

Jonathan Wakely