Question

Consider the following code:

class A
{
private:
    class B {};
public:
    B f();
};

A a;

A::B g()
{
    return a.f();
}

The compiler rejects this - g cannot return A::B because A::B is private.

But suppose I now use decltype to specify the return value of g:

class A
{
private:
    class B {};
public:
    B f();
};

A a;

decltype(a.f()) g()
{
    return a.f();
}

All of a sudden it compiles fine (with g++ >= 4.4).

So I've basically used decltype to get around an access specifier in a way I would not have been able to in C++98.

Is this intentional? Is this good practice?

Was it helpful?

Solution

Access only applies to names (and as a special case, to constructors/destructors). It doesn't apply to entities themselves. The spec further elaborates

[ Note: because access control applies to names, if access control is applied to a typedef name, only the accessibility of the typedef name itself is considered. The accessibility of the entity referred to by the typedef is not considered. For example,

class A {
  class B { };
public:
  typedef B BB;
};

void f() {
  A::BB x; // OK, typedef name A::BB is public
  A::B y; // access error, A::B is private
}

— end note ]

So what you have disovered here isn't surprising. You can get hold of the type A::B even in C++03, when taking the address of f by saying &A::f and passing it to a function template deducing the return type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top