0
votes

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.

1
imho forward-declarations are already a code-smell, but playing tricks just to make it even less obvious what a header depends on is really bad - 463035818_is_not_a_number
@user463035818 Forward declarations can be extremely powerful in reducing compile time for large projects. It can be used to limit how much needs to be recompiled when changing a header. - François Andrieux
@user463035818: Not having forward declarations is the code smell. - Lightness Races in Orbit
Not really sure how to answer this question. We can discuss the different kinds of lookup and the constraints of each one. We can discuss whether you can forward declare with an elaborated type specifier, but you've already done that in the question. So what are you after here, really? - Lightness Races in Orbit
@Lightness Races in Orbit 1), Is this inadvisable instead of forward declarations? 2) Out of curiosity is there a way to do this with namespaces? - Zebrafish

1 Answers

2
votes

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.