3

I know that after a forward declaration such as

class Foo;

I can declare a variable as Foo* or Foo&, but not Foo.

If I have a templated class and instantiation

template<class T>
class Bar {
  public:
    T baz;
};
...
Bar<Foo> v;

how would the above rule apply? Would Foo have to have been fully declared (as opposed to only forward declared) at the point the class Bar is defined, or at the point v is declared? Or maybe it only has to be at one point that Bar<Foo> is used anywhere in the source files, and all the others it is not? Something else?

Thanks

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Baruch
  • 20,590
  • 28
  • 126
  • 201

2 Answers2

5

Bar<Foo> requires the full Foo definition because it contains a data member of type Foo. You could not forward declare in this case. In this respect, Bar<Foo> is the equivalent of

class BarFoo 
{  
 public:
    Foo baz;
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • But where is it required? Only at the `Bar` usage, or is it retroactively at the definition of `Bar`? – Baruch Jan 08 '14 at 22:05
  • 3
    @baruch only when you instantiate the type `Bar`. The class template `Bar` knows nothing about `Foo`. Otherwise templates would not work at all. – juanchopanza Jan 08 '14 at 22:06
0

To answer your question, you just have to mentally replace T with the template argument type:

template<class T>
class Bar {
public:
    T baz;
};

With this method, the above code will change to:

class Bar {
public:
    Foo baz;
};

Now, as you know, the compiler will need the full declaration of Foo in order to know how much size to allocate when declaring a Bar object.

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • Yes, but the question was where this replacement takes place, and so where the full deceleration of `Foo` has to be known: At first instantiation, at each one, or retroactively at the `Bar` definition? – Baruch Jan 09 '14 at 07:22
  • @baruch, when you use `Bar`. – Shoe Jan 09 '14 at 16:23