Search code examples
c++classnamespacesforward-declaration

Can I avoid forward declarations by specifying struct or class


Up until now I thought that you had to forward declare types before using them in class definitions until I found out about elaborated type specifier. So instead of forward declaring everything like:

struct Banana;
struct Apple;
struct Kiwi;
struct Orange;
struct Mango;
struct Lemon;
struct Plum;

I can do:

struct FruitStuff
{
    struct Banana* banana;
    struct Apple returnApple();
    void eatKiwi(const struct Kiwi& kiwi);
    void peelOrange(struct Orange orange);
    std::vector<struct Mango> mangos;
    static struct Lemon* lemons[10];
    void pickPlum(const struct Plum *const plum);
};

Define these in the appropriate cpp or whatever, and not have to forward declare anything. I think I prefer this way, but is this inadvisable or a bad idea in any way?

Also, I've noticed this trick doesn't work for namespaces, because:

namespace FruitNamespace
{
    void pickPlum(struct Plum * plum) {}; // The compiler thinks that the Plum argument 
                                           // here is FruitStuff::Plum*
}
// so
struct Plum {int a;}

int main()
{
    Plum plum;
    FruitNamespace::pickPlum(&plum); // argument of type "Plum *" is incompatible
                                     // with parameter of type "FruitNamespace::Plum *" 

}

It's funny how if I specify a struct inside a struct it simply expects any struct by that name, but in a namespace it expects a struct within that namespace. It's not important, but out of curiosity I'm wondering if there's a way around this.


Solution

  • An elaborated type specifier declares the class just like a separate declaration does. There is no technical reason to avoid declaring a class with an elaborate type specifier - they are part of the language, their use is well defined and they are not deprecated.

    Of course, one has to be aware - as you are - that the elaborated type specifier declares the class into the current namespace, and if that is not desired then the class has to be declared separately outside of current namespace. There's no trick to avoid that that that I'm aware of. As such, not all forward declarations can be done using elaborated type specifiers.

    For cases that can be implemented either with a separate declaration, or an elaborated type specifier, the choice between one over the other is a matter of personal preference.