Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ header-only library avoid "using namespace" pollution

I have a header-only C++ library with several namespaces.

For example one header file may contain

//header1.h
namespace library{
namespace componentA{
   template<typename T>
   class Someclass{};
}
}

And another one

//header2.h
namespace library{
namespace componentB{
   template<typename T>
   class SomeOtherClass{
       void Foo(const componentA::Someclass<T>& reference);
       void Bar(const componentA::Someclass<T>& reference);
   };
}
}

Now while this works, having a header-only library it becomes tedious to write the namespace again and again, especially when you are having multiple classes and nested namespaces involved.

So I did this:

//new header2.h
namespace library{
namespace componentB{

   using namespace componentA;

   template<typename T>
   class SomeOtherClass{
       void Foo(const Someclass<T>& reference);
       void Bar(const Someclass<T>& reference);
       void FooBar(const Someclass<T>& reference);
       void FooWithBar(const Someclass<T>& reference);
   };
}
}

While this is certainly more convenient to type, it has the problem that now a client of the library can also use Someclass<T> by using the componentB namespace like this, which leads to an ambiguous interface and ultimately to inconsistent code. For example a client now could use componentB::Someclass<T> even though it is originally defined in componentA

Is there a way to get the shorthand only available "privately"?

like image 551
worenga Avatar asked May 11 '26 08:05

worenga


2 Answers

namespace library {
  namespace componentAImpl{
    using ::library::componentB;
    // ...
    inline namespace exports{
      struct foo{};
    }
  }
  namespace componentA{
    using namespace library::componentAImpl::exports;
  }
}

users can access componentAImpl, but should not.

Meanwhile, a clean set of symbols are exposed in library::componentA.

like image 178
Yakk - Adam Nevraumont Avatar answered May 13 '26 00:05

Yakk - Adam Nevraumont


If I understand your question correctly, then the answer is no. If typing/reading componentA:: before type names from the componentA namespace is too much of a problem (honestly, that would be my preference), then you could use short namespace aliases:

namespace library { namespace componentB
{
// ...
namespace ca = componentA;
// ...
void foo(ca::SomeClass<T>);
// ...
} }

In any case, I discourage using directives in header files: they lead to name clashes and maintenance issues.

like image 21
Andy Prowl Avatar answered May 13 '26 00:05

Andy Prowl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!