6
\$\begingroup\$

I am writing some library code that is mostly templates and so is all contained in header files. I know that placing a using declaration in a header will pollute all the files that include it, but I'm also starting to be really annoyed by having to spell out all the namespaces.. After a bit of tinkering I came up with these macros:

#define MACRO_CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) MACRO_CONCAT_IMPL( x, y )

#define PRIVATE_NAMESPACE_IMPL( name ) namespace name { namespace exports{} } using namespace name::exports; namespace name {

#define PRIVATE_NAMESPACE PRIVATE_NAMESPACE_IMPL(MACRO_CONCAT(private_namespace_,__COUNTER__))
#define END_PRIVATE_NAMESPACE }

#define PUBLIC_SECTION namespace exports{
#define END_PUBLIC_SECTION }

To be used like this:

namespace MyNamespace{

PRIVATE_NAMESPACE

    using namespace std;
    using namespace ThirdParty::Library;
    using namespace MyCompany::OtherProduct;

PUBLIC_SECTION

    class Class{
        wstring GetString();
    };
END_PUBLIC_SECTION

END_PRIVATE_NAMESPACE

}

This will create a private namespace with the using declarations and a nested one with the publicly available code that is then imported into the topmost namespace (MyNamespace).

This is different from a plain nested namespace as it expands into this:

namespace MyNamespace{
    namespace private_namespace_0{

      using namespace std;
      using namespace ThirdParty::Library;
      using namespace MyCompany::OtherProduct;

      namespace exports{
            class Class{
                wstring GetString();
            };
        }
    }
    using namespace private_namespace_0::exports;
}

This way the "public" section has access to the "private" one and only the public one is accessible with MyNamespace::. The weird thing with the counter is to ensure each header has its own private namespace so that declarations are not shared between separate header files. Giving an ID to the namespaces is also the only reason that i'm using macros.

Using a "private" namespace seems to be accepted practice as boost does it too. I also know that __COUNTER__ isn't really portable but vc++ and gcc both support it..

Is there anything really wrong with this idea or a better/standard way to do it?

\$\endgroup\$
  • 8
    \$\begingroup\$ Yes it is stupid. Stop it. \$\endgroup\$ – Martin York Feb 10 '12 at 5:37
  • 1
    \$\begingroup\$ I agree that you shouldn't do it, but you're getting a +1 for noticing that there might be something wrong with your approach. \$\endgroup\$ – João Portela Feb 10 '12 at 16:16
5
\$\begingroup\$

You're writing a lot of code, but what is the benefit? How is this any worse?

namespace MyNamespace {
    namespace ImplDetails {
        // Non-public code.
    }
    // Public code.
}

Yes, people can access things in ImplDetails, but you can't get around that sanely. Obscuring namespace names is only going to hurt compatibility (when a namespace gets renamed after you insert a new one, which will happen eventually). If people want to access your internals, they will.

\$\endgroup\$
  • \$\begingroup\$ I updated my question! \$\endgroup\$ – Roald Feb 10 '12 at 19:18
  • \$\begingroup\$ @Roald: Your premise is flawed: the code is just as accessible with MyNamespace::private_namespace_n::exports. I'm somewhat surprised __COUNTER__ works when files are built one by one, by the way, and you can still run into problems if you add more files. \$\endgroup\$ – Anton Golov Feb 10 '12 at 20:45
  • \$\begingroup\$ I'm not trying to make it really private.. that wasn't my goal. I just want to have using namespace ; statements that don't leak out of the header. I know that someone can still get to them if they really want to but that's not the point. You can now safely say: "using namespace MyNamspace;" in a .cpp without importing the additional namespaces used in the header. The counter can have a different value every time the file is included, I'm not relaying on that, there are no direct references to private_namespace_n besides the one the macro makes. Adding files would not really change anything.. \$\endgroup\$ – Roald Feb 10 '12 at 21:09
  • \$\begingroup\$ @Raold: Ah, I see. I would advise just using less using-directives. Yes, what you're doing gives you somewhat easier access to the names, but really, is renaming the third-party namespaces (and not using namespace std;, of course) really end up with your code being unreadable? I would say that the macro does more damage to readability than some qualifiers would. \$\endgroup\$ – Anton Golov Feb 10 '12 at 21:34
1
\$\begingroup\$

Make a private namespace to be used separately.Why are you trying to complicate things

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.