views:

115

answers:

1

Howdy,

I am attempting to use the fully qualified name of my nested class as below, but the compiler is balking!

template <class T> class Apple {
    //constructors, members, whatevers, etc...
public:
    class Banana {
    public:
        Banana() {
            //etc...
        }
        //other constructors, members, etc...
    };
};

template <class K> class Carrot{
public:
    //etc...
    void problemFunction()
    {
        Apple<int>::Banana freshBanana = someVar.returnsABanana(); //line 85
        giveMonkey(freshBanana);  //line 86
    }
};

My issue is, the compiler says:

Carrot.h:85: error: expected ';' before 'freshBanana'
Carrot.h:86: error: 'freshBanana' was not declared in this scope

I had thought that using the fully qualified name permitted me to access this nested class? It's probably going to smack me in the face, but what on earth am I not seeing here??

+6  A: 

That's probably not what you do in your code. The error message looks like you do this

Apple<K>::Banana freshBanana = someVar.returnsABanana();

The compiler has to know before it parses the code whether a name names a type or not. In this case, when it parses, it cannot know because what type K is, is not yet known (you could have a specialization for Apple<int> that doesn't have that nested class). So it assumes Apple<K>::Banana is not a type. But then, it is an expression and an operator is needed after it or a semicolon.

You can fix it by inserting typename:

typename Apple<K>::Banana freshBanana = someVar.returnsABanana();

That asserts the name is a type, and the compiler then knows to parse this as a declaration.

Johannes Schaub - litb
sadly, no. Although I DID oversimplify. Above, I declare:typedef Apple<int> IntyApple;So the line is actually:IntyApple::Banana freshBanana = someVar.returnsABanana();Thanks for the answer, though!
Nate
Although, I actually jumped the gun. Your suggestion of typename actually did make my error go away... perhaps my situation is more complicated than I am realizing. So thank you!
Nate
@Nate, The Standard rules "Within the scope of a class template, when the unqualified name of a nested class of the class template is referred to, it is equivalent to the name of the nested class qualified by the name of the enclosing class template." (which would make it dependent) but that doesn't apply here because the typedef is not a nested class. It would look like a compiler bug to me. For nested classes, making them dependent this way is important, because you could specialize these nested classes for certain template parameters. However, you can't do that for typedefs.
Johannes Schaub - litb
Aha... then what I thought was a valid oversimplification above actually reveals my bug. I was subbing "int" in for a pointer. Usually not an unreasonable substitution, no? Sadly, in this case it was a pointer to another nested class inside Carrot<K>. Expanded, this would cause the behavior you described!
Nate
@Nate yes in fact i think that's the problem here, then :)
Johannes Schaub - litb