8

If I want to use a pointer to a class and I dont do any operations on it, we can forward declare the class. But if that happens to be a typedef, why is it not allowed? In the following example, it compiles only i include the commented code but why does compiler wants to know about it at that point? How do I forward declare something which may be a typedef. Is there any changes in this behavior in c++0x?

#include <iostream>
using namespace std;
/*
template<class T>
class temp;

typedef temp<int> later;
*/
class later;
void somefunc(later*);
int main()
{
  later* l;
  somefunc(l);
  return 0;
}
//The following is in someother file/compilation unit.
template<class T>
struct temp
{
  public:
    void print()
    {
        T t(5);
        std::cout<< "helloworld: " << t << std::endl;
    }
};
typedef temp<int> later;
void somefunc(later* l)
{
  l = new later();
  l->print();
}
balki
  • 26,394
  • 30
  • 105
  • 151

1 Answers1

6

A typedef does not create a type it just adds a new name to an existing type, and you cannot forward declare it. I recommend that you read this answer to a different related question, I think it can help in understanding the differences between a typedef and a declaration of a user defined type.

You can, on the other hand, forward declare the actual type, and then add the typedef in place.

EDIT: Extending on your particular example:

After declaring the temp template, the identifier temp is available in the user defined types identifier space (which is different to the rest of the symbols' identifier space). The typedef will create an alias in the global identifier space by the name of later, so after the commented lines (were they uncommented), the user defined types identifier space will contain temp referring to the template, and the identifier later residing in the global identifier space will refer to the concrete instantiation temp<int>. (What a mouthful of "identifier" and "space"!)

On the other hand, if you forward declare the class as in the first uncommented line class later;, what you are doing is adding an identifier to the user defined types identifier space. The difference can be seen in the following example:

class A;           // Creates A identifier only in user defined types space
typedef int B;     // Creates B identifier in the global identifier space

void A(){}         // Ok: A will refer to void A(); class A will refer to the type
//void B(){}       // Error: B symbol collides with the typedef
Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Yes, I understand this but why is it so? However it is eventually going to point a type. Does it not break the use of forward declaration? – balki Jun 22 '11 at 10:21
  • @balki: it does :/ For example, most people will `#include ` rather than going the long road and forward declare `std::basic_string`. – Matthieu M. Jun 22 '11 at 10:23
  • @balki: I have added a link to an answer to a different question, where the semantics of `typedef` are explained. The original question is C, but it applies here, and the answer has some C++ content to it. Basically, a user defined type declaration adds the type (and potentially an identifier that refers to it) to the user defined identifier space, while a `typedef` creates an identifier in a different identifier space that refers to a given type. – David Rodríguez - dribeas Jun 22 '11 at 10:24
  • @Matthieu: You cannot forward declare std::basic_string. –  Jun 22 '11 at 10:42
  • @Fanael: you can `template class basic_string;` physically, was the question whether you are allowed to or not ? – Matthieu M. Jun 22 '11 at 12:09
  • @Fanael: in gcc, see the `bits/stringfwd.h` header. – Matthieu M. Jun 22 '11 at 12:15
  • If you did that in namespace std, it would be undefined behavior. Standard library implementors are allowed to do that, you're not. –  Jun 22 '11 at 12:18