0

Preface

I'm trying to increase my C++ code robustness and, for quite some time, I have been plagued with the issue of namespace pollution.

Because using namespace::std; is a obvious bad practice, I have always explicitly declared my intentions when using data structures and functions from other namespaces, by using using std::array declarations inside the namespace where I implement my data structures.

But this can still be a problem. For example, if I have a namespace called products and, if I declare all of my products data structures inside the products namespace, namespace pollution will still occur, due to the increase of using std::XYZ declarations.

It can easily get to a point where, when using the Eclipse CDT indexer, I will see more standard types, functions and data structures inside my own namespaces, than the data types that I myself have implemented.

My Unsuccessful Solution

In order to achieve some contention, I decided to try the Boost Lib example and isolate the data structures implementation in their own namespace. Boost uses the detail namespace for this. But now I have a bigger problem because of the C++ friendship mechanism and how data and functions are declared in namespaces.

The following code uses the c++ friendship mechanism in order to prevent the instantiation of ProductA by any other object except for the FactoryA objects. It also follows my attempt to isolate the namespace where ProductA is declared.

Product A Code

#ifndef PRODUCT_A_GUARD__
#define PRODUCT_A_GUARD__

namespace factories {
  class FactoryA;
}

namespace products {
  namespace productA_detail {
    using std::uint32_t;
    using std::size_t;

    class ProductA {
        friend class factories::FactoryA;

        const uint32_t productID;

        ProductA(const uint32_t& productID)
        : productID{productID}
        {}

      public:
        virtual 
        ~ProductA() {}
    };
  }

  using productA_detail::ProductA;
}
#endif //PRODUCT_A_GUARD__

Factory A Code

#ifndef FACTORY_A_GUARD__
#define FACTORY_A_GUARD__

#include <memory>
#include "productA.hpp"

namespace factories {
  namespace FactoryA_detail {
    using std::uint32_t;
    using std::unique_ptr;
    using products::ProductA;

    class FactoryA {
      uint32_t created_products {0};

     public:
        FactoryA() {}

        unique_ptr<ProductA> Created_ProductA() {
          return unique_ptr<ProductA>(new ProductA(created_products++));
        }

        virtual 
        ~FactoryA() {}
    };
  }

  using FactoryA_detail::FactoryA;
}
#endif //FACTORY_A_GUARD__

Main

#include <memory>
#include "factoryA.hpp"
#include "productA.hpp"

int main (){
  using std::unique_ptr;
  using factories::FactoryA;
  using products::ProductA;

  FactoryA factory;
  unique_ptr<ProductA> product = factory.Created_ProductA();
  return 0;
}

This code will not compile with GCC 6.2 The compiler will complain about FactoryA being already declared at the factories namespace

In file included from test.cpp:4:0:
factoryA.hpp: At global scope:
factoryA.hpp:29:26: error: ‘FactoryA’ is already declared in this scope
   using FactoryA_detail::FactoryA;

Because of this issue, I'm unable to devise a helpful way to prevent a namespace pollution by the constant use of the using std::XYZ declarations and, still be able to make use of the C++ friendship mechanism to prevent misuse of some of my data structures.

Does anyone know a way to achieve my objective or, if it is possible to be achieved in the first place?

Community
  • 1
  • 1
  • 1
    Perhaps you have too many namespaces? Generally, you don't need to use namespaces for architectural purposes. –  Dec 13 '16 at 02:31
  • 2
    Also, names with double underscores in them are reserved for the implementation. –  Dec 13 '16 at 02:44
  • What's the point of `productA_detail` and `FactoryA_detail`? Why this two-step dance of wrapping a class in an extra namespace then fetching it back out? As to namespace pollution - just say No to `using` directives in headers (at least, at namespace scope); spell out fully qualified names for everything. The directives are OK in source files. – Igor Tandetnik Dec 13 '16 at 02:53
  • My intention is to isolate, for example, the std::array from my products namespace. I want to reduce the size of the code, since I use boost libs and they usually have deep and long namespaces. doing like you are suggesting, will increase the size of my code and seriously reducing its legibility. The two-step dance, like you call it, prevents the namespace pollution of the products namespace. This is not my idea, Boost uses the same concept. I was just trying to apply it to my use-case. – Carlos Ferreira Dec 13 '16 at 03:00
  • 2
    Can you point to instances in Boost where they use this? I've seen them declare functions in nested namespaces and hoist them into the `boost` namespace with using declarations/directives, but those are to prevent the functions from being found by ADL. You seem to be creating problems for yourself by unnecessarily deep namespace hierarchies. And the problem of long Boost namespace names can be solved by creating namespace aliases. – Praetorian Dec 13 '16 at 03:16
  • Sure! Boost.Math uses it [here](http://www.boost.org/doc/libs/1_62_0/boost/math/special_functions/detail/t_distribution_inv.hpp) Notice the boost::math::detail namespace. They also use fully qualified names, like the example Igor was previously suggesting. I also found a similar example [here at SO](http://stackoverflow.com/questions/4424141/c-using-for-std-and-boost-namespace-best-practice). – Carlos Ferreira Dec 13 '16 at 10:54
  • That looks like a different use case to me. Putting implementation details in a `detail` namespace is fairly common practice. Functions in the public `boost::math` namespace will then call the implementation detail functions, but I don't see them hoisting the functions in the `detail` namespace into the `boost::math` namespace. In your case, it looks like `ProductA` is not an implementation detail, but a type that clients will create and interact with. In any case, if you insist on following your pattern, you'll need to live with its limitations too. – Praetorian Dec 13 '16 at 17:19
  • I'm actually open to suggestions that can help me to avoid "spelling out" the entire qualified names. It's not visually appealing and I want a code free from having `A::B::C::D::E::F::G` ... I'm not going to use the practice that I have presented, because it breaks the friendly mechanism. – Carlos Ferreira Dec 13 '16 at 18:00
  • I did suggest a solution to that problem in my first comment - [namespace aliases](http://en.cppreference.com/w/cpp/language/namespace_alias). `namespace blah = A::B::C::D::E::F::G;` – Praetorian Dec 14 '16 at 05:38
  • I though you were refering to the creation of aliases for specific data types, like `using blah = A::B::C::D::E::F::G::dataType;` I tried this but it wouldn't work well for templates. My bad. – Carlos Ferreira Dec 14 '16 at 14:11
  • I have decided to follow a different approach. Instead of declaring aliases inside the namespaces, I will do them closer to where they are used, in function scope or class declaration scope. I will still have the issue of the return types declarations in functions. Like you (Praetorian) said, I have to live with current limitations. I know that these issues will be addressed with modules (C++20?), so when that time arrives, I will resolve the issue. – Carlos Ferreira Dec 14 '16 at 14:23

0 Answers0