I think that this isn't allowed. Although there's a note in the standard that
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.
So in
struct block : base
the name base
is accessible. However the typedef itself uses the name foo::impl
, which is private and therefore inaccessible. The name also would be inaccessible in the static_assert.
I don't see any exceptions that would allow the name to be accessed in these contexts.
My compiler produces these errors for this code:
main.cpp:16:27: error: 'impl' is a private member of 'foo'
static_assert(sizeof(foo::impl) == 16, "paranoia");
^
main.cpp:4:12: note: declared private here
struct impl; // forward-declared
^
main.cpp:19:27: error: 'impl' is a private member of 'foo'
typedef typename foo::impl base;
^
main.cpp:4:12: note: declared private here
struct impl; // forward-declared
^
One option might be to include a public friend in foo
, which will have access to the private names inside foo
. Then you can place the definition of that friend type in the cpp file so that the names it exposes are exposed only in that one file:
// header
struct foo {
struct private_public_access;
private:
struct impl;
};
// cpp
struct foo::impl {};
struct private_public_access {
typedef foo::impl foo_impl;
};
typedef private_public_access::foo_impl base;
Anyone will be able to use the name private_public_access
, but they won't have the definition and so won't be able to access private_public_access::foo_impl
(although they could define it themselves to gain access...). Although if this is acceptable then maybe it'd be just as acceptable to leave the name foo::impl
public and its definition hidden like it already is (and like private_public_access
's definition is hidden).