I have a private
data structure buried within many nested namespaces & classes as shown in the (simplified) example below. The private
structure contains numerous static const
members (lengthy STL containers, mostly), represented in this example by a single static const int i
.
Note: the presence of the const
here doesn't seem to bear on my problem; it's included merely for the sake of completeness.
#include <iostream>
using std::cout; using std::endl;
namespace foo {
namespace bar {
class MyClass {
struct Data {
static const int i;
// ... + many more
};
public:
int Get() const { return Data::i; }
};
}
}
/////////////////////////////////////////////////////////////////////////////
const int foo::bar::MyClass::Data::i = 42; // [A] <- Verbose; but works fine
// ... + many more // [A]
//using concise = foo::bar::MyClass::Data; // [B] <- Nope; 'Data' is private
//const int concise::i = 42; // [B] <- Ideally
//// ... + many more // [B]
/////////////////////////////////////////////////////////////////////////////
int main()
{
cout << foo::bar::MyClass{}.Get() << endl;
return 0;
}
Defining static members such as i
outside of their data structure is trivial (see [A]
). However, as the number of namespaces/classes/structs in a member's hierarchy grows, it becomes desirable to abbreviate the hierarchy (chain/tree/prefix?) in the member's definition for the sake of readability.
Imagine something like the following was required, many times over:
const std::vector<std::string> foo::bar::baz::MyClass::MySubClass::MySubSubClass::PrivateDataStruct::vecOfStr = {…};
At some point, for the coder's sanity, they would want to shorten the syntax of this operation.
My naive attempt (see [B]
) at aliasing the definition of i
via the using
directive has not worked as expected due to the Data
structure being private
. Swapping code block [B]
for [A]
yields (in VS2017):
error C2248: 'foo::bar::MyClass::Data': cannot access private struct declared in class 'foo::bar::MyClass'
Ideone (gcc?) results in a similar error at [B]
:
error: ‘struct foo::bar::MyClass::Data’ is private within this context
[B]
work, while [A]
does?i
with its hierarchy chain/tree/prefix aliased (preferably via using
)?Other questions (such as using alias for static member functions?) hew closely to mine, but don't seem to pertain.
Please feel free to improve this question with any edits or suggestions.
Why doesn't [B] work, while [A] does?
private
stuff (class/member name) can only be used at several places, including definitions (which is [A]) but not aliases (in scope not allowed to use types)
How might I define
i
with its hierarchy chain/tree/prefix aliased (preferably via using)? Bonus: What is the preferred nomenclature for what I've been calling the namespace/class/structure hierarchy chain/tree/prefix when referencing a member?
You might still shorten the namespace part:
using namespace foo::bar;
const int MyClass::Data::i = 42;
And for the class part, you can still add some using in parent class, if acceptable:
class MyClass {
class MySubClass{
friend class MyClass;
class MySubSubClass{
friend class MyClass;
class PrivateDataStruct {
static const std::vector<std::string> vecOfStr;
// ...
};
// ...
};
// ...
};
using inner = MySubClass::MySubSubClass::PrivateDataStruct;
public:
// ...
};
And finally:
const std::vector<std::string>
foo::bar::baz::MyClass::MySubClass::MySubSubClass::PrivateDataStruct::vecOfStr = {/*…*/};
becomes:
using namespace foo::bar::baz;
const std::vector<std::string> MyClass::inner::vecOfStr = {/*…*/};