R
Rennie deGraaf
From time to time, I need to define a class that isn't part of the
public API of whatever library or module that I'm developing, but still
needs to be in the header file because it's used by some class that is
in the public API. In Java, I'd use something like /package/ visiblity
on such classes within the package I'm developing, and use /public/
visibilty on classes in the public API. In C++, the best I've been able
to come up with is something like this:
namespace SomeNS
{
class _PseudoNS
{
private:
_PseudoNS() {} // _PseudoNS is non-instantiable
class ImplementationDetail {/* ... */};
friend class PublicAPI;
public:
class APIObject : public ImplementationDetail {/* ... */};
};
typedef _PseudoNS::APIObject APIObject;
class PublicAPI
{
private:
std::vector<APIObject> internalData;
/* ... */
};
}
This works, but it isn't a particularly good solution. Since _PseudoNS
isn't really a namespace, you can say "using _PseudoNS::APIObject";
that's why I have the typedef in there. If APIObject is a template,
rather than a class, then you can't typedef it (I'm aware that this
problem is already scheduled to be fixed in C++0x), and you have to
refer to it as "_PseudoNS::APIObject" all the time. Also, since
_PseudoNS is really a class and PublicAPI has access to its constructor,
it's possible for someone to accidentally instantiate it from within
PublicAPI, which is (or at least, should be) a totally meaningless
operation. The compiler will also have to compile _PseudoNS as a class,
which wastes time and storage space. What I'd like to see would be
extensions to the language to support something like this:
static namespace SomeNS
{
private:
class ImplementationDetail {/* ... */};
public:
class APIObject : public ImplementationDetail {/* ... /*};
class PublicAPI
{
private:
std::vector<APIObject> internalData;
/* ... */;
};
}
A /static namespace/ (maybe /const namespace/ would be a better term?)
would then be a namespace that cannot be re-opened. /Private/ symbols
within it would be visible only to other members of the namespace, and
public symbols would be accessible from outside. I don't think that
there would be any meaning for a /protected/ visibility class.
Of course, an extension like this could throw a few wrenches into other
stuff. One could probably make a case that if this was acceptable, then
you should also be allowed to do this:
static namespace SomeNS
{
friend namespace SomeOtherNS;
/* ... */
}
Any thoughts?
Rennie deGraaf
public API of whatever library or module that I'm developing, but still
needs to be in the header file because it's used by some class that is
in the public API. In Java, I'd use something like /package/ visiblity
on such classes within the package I'm developing, and use /public/
visibilty on classes in the public API. In C++, the best I've been able
to come up with is something like this:
namespace SomeNS
{
class _PseudoNS
{
private:
_PseudoNS() {} // _PseudoNS is non-instantiable
class ImplementationDetail {/* ... */};
friend class PublicAPI;
public:
class APIObject : public ImplementationDetail {/* ... */};
};
typedef _PseudoNS::APIObject APIObject;
class PublicAPI
{
private:
std::vector<APIObject> internalData;
/* ... */
};
}
This works, but it isn't a particularly good solution. Since _PseudoNS
isn't really a namespace, you can say "using _PseudoNS::APIObject";
that's why I have the typedef in there. If APIObject is a template,
rather than a class, then you can't typedef it (I'm aware that this
problem is already scheduled to be fixed in C++0x), and you have to
refer to it as "_PseudoNS::APIObject" all the time. Also, since
_PseudoNS is really a class and PublicAPI has access to its constructor,
it's possible for someone to accidentally instantiate it from within
PublicAPI, which is (or at least, should be) a totally meaningless
operation. The compiler will also have to compile _PseudoNS as a class,
which wastes time and storage space. What I'd like to see would be
extensions to the language to support something like this:
static namespace SomeNS
{
private:
class ImplementationDetail {/* ... */};
public:
class APIObject : public ImplementationDetail {/* ... /*};
class PublicAPI
{
private:
std::vector<APIObject> internalData;
/* ... */;
};
}
A /static namespace/ (maybe /const namespace/ would be a better term?)
would then be a namespace that cannot be re-opened. /Private/ symbols
within it would be visible only to other members of the namespace, and
public symbols would be accessible from outside. I don't think that
there would be any meaning for a /protected/ visibility class.
Of course, an extension like this could throw a few wrenches into other
stuff. One could probably make a case that if this was acceptable, then
you should also be allowed to do this:
static namespace SomeNS
{
friend namespace SomeOtherNS;
/* ... */
}
Any thoughts?
Rennie deGraaf