4

For example, take this snippet of code:

class Foo;
class Something {
    Foo *thing;
};
typedef std::vector<Something> Foo;

This doesn't compile, because Foo is already a type when the typedef is hit. However, I think it shows my use case; I have cyclical dependencies and need one to fulfill the other, but (currently) one of the things is typedef'd. I'd prefer not to write something like

class Foo {
    std::vector<Something> inside;
}

because then I need to remember the inside in every my_foo.inside.some_method(). I'd also like to avoid writing a wrapper around std::vector<Something>, because it'd be a lot of boilerplate.

How can I forward declare a type which I'm defining with a typedef? Alternatively, how can I resolve my problem of cyclical dependencies without using one of the solutions above? Is it possible at all?

Note that I'm not asking "How can I typedef with a type that hasn't been declared yet". I'm asking "How can I use typedef to define a previously-declared type".

Nic
  • 6,211
  • 10
  • 46
  • 69

1 Answers1

8

Forward declare the class instead:

class Something;
typedef std::vector<Something> Foo;
class Something { Foo *thing; };

If you are using C++11 revision or greater, use an using declaration in place of a typedef:

class Something;
using Foo = std::vector<Something>;
class Something { Foo *thing; };

And that's all.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • ...oh. Duh. I'm smart. – Nic Aug 22 '16 at 19:50
  • Is there a particular reason to use `using` over `typedef`? I know it matters when you want to use templated nicknames, but that's not the case here. – Nic Aug 22 '16 at 19:51
  • 1
    @QPaysTaxes I'd say _because we are living the 2016_, but it's also far clearer to me as a declaration. – skypjack Aug 22 '16 at 19:53
  • 1
    http://stackoverflow.com/questions/10747810/what-is-the-difference-between-typedef-and-using-in-c11 - also, looks more similar to `using namespace foo;` and `using foo::bar;` - just nice to keep to one keyword :) – Jesper Juhl Aug 22 '16 at 19:54
  • Are you sure this is legal? You can't create a standard container of forward declared objects, which seems to be exactly what's going on here. – Mark B Aug 22 '16 at 19:59
  • @MarkB But typedefs don't need complete types. It has to be a complete type when _used_, and it is -- the forward-declared class is defined immediately after the typedef, before any code that uses either it or them. – Nic Aug 22 '16 at 20:00
  • @MarkB Yes, I'm sure it is legal, but [you can try it for yourself](https://godbolt.org/g/2xySwq). – skypjack Aug 22 '16 at 20:02
  • @QPaysTaxes What I'm seeing is that `Something` has a pointer to a `vector`, and *inside the definition of `Something`*, `Something` is not fully defined. @skypjack I'm asking if you can provide the standard reference showing it's *legal* not showing that a particular compiler can compile it. – Mark B Aug 22 '16 at 20:04
  • @MarkB Apart for the fact that you can try it with more than _a particular compiler_, I'll find for you the sections in the reference that you are asking fot (as soon as I can, it's past 22 in Italy). – skypjack Aug 22 '16 at 20:06
  • @MarkB [Here](http://eel.is/c++draft/containers#vector.overview-3) we are (maybe) - _An incomplete type T may be used when instantiating vector_. – skypjack Aug 22 '16 at 20:09
  • 1
    @MarkB Oh, I see. That's not actually the use case; I'm actually taking a reference to the typedef'd type (for more reasons than just that), so it all works out – Nic Aug 22 '16 at 20:17
  • @MarkB: incomplete type for vector was supported by most compiler even if standard stated (indirectly ?) that it was UB. Should be allowed in C++17. See [can-i-manage-incomplete-class-objects-using-stl-containers](http://stackoverflow.com/questions/31858878/can-i-manage-incomplete-class-objects-using-stl-containers) – Jarod42 Aug 22 '16 at 20:51
  • @Jarod42 Fair enough. I got the reference from the working draft indeed. – skypjack Aug 22 '16 at 20:54