Nested class using declaration and access modifiers
Asked Answered
A

1

6

while compiling some code that I ran into a compiler error that seemed strange to me and relates to inheritance, nested classes, using declarations, and access modifiers.

Basically, the intention is for a derived type to expose a nested protected class of a base type.

The the following short example to demonstrate the issue:

class Base
{
protected:

    struct Nested
    {
        enum value_enum
        {
            val = 0,
            val2,
            val3
        };
    };

};

class Derived : public Base
{
public:

    using Base::Nested;
};


int main(int argc, char** argv)
{
    //Base::Nested aa; // error, as (I) expected
    //Base::Nested::value_enum ab; // error, as (I) expected

    Derived::Nested ba; // works, as (I) expected
    Derived::Nested::value_enum bb; // MSVC error, as (I) did not expect


    return 0;
}

See live.

MSVC11 (v11.00.61030) chokes on this code with the following error:

error C2248: 'Base::Nested' : cannot access protected struct declared in class 'Base'

Both GCC and Clang compile this properly, so without the ability to quote the relevant parts from the standard, I would argue this is an MSVC bug.

Is there a way around this with MSVC?

Amperehour answered 7/9, 2015 at 10:28 Comment(5)
I think getting an error at compile time is better than running in to problems latter.Haunch
Since its protected, by standard main function will not be able to access itHaunch
@AliKazmi What is protected? Derived changes the access modifier for Nested; it is not protected in this case. Also, value_enum is not protected inside Nested.Amperehour
Try typedef Base::Nested::value_enum value_enum; in Derived class.Damoiselle
@Damoiselle MSVC does not complain about a typedef Base::Nested Nested (There are other types, etc; since is was only an SSCCE). I "like" that idea as a workaround.Amperehour
D
1

For MSVC the following workaround works:

class Derived : public Base
{
    public:

    using Base::Nested;
    typedef Base::Nested::value_enum value_enum; // add this
};

int main(int argc, char** argv)
{
    //Base::Nested aa; // error, as (I) expected
    //Base::Nested::value_enum ab; // error, as (I) expected

    Derived::Nested ba; // works, as (I) expected
    Derived::value_enum bb = Derived::value_enum::val; // now works in MSVC


    return 0;
}
Drafty answered 5/1, 2016 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.