4

I'd love to be able to use references to another namespace within a class without committing the error/sin of introducing that namespace into my caller's compilation units.

The only way I am aware of to do that now is to move everything into my .cpp file, where I can declare a using namespace XYZ without worries.

But what if I'm defining a template? Or I just want to put this code in my header?

For example, I want to use namespace Toolbox from which Toolbox::FormatString lives, and there are many other useful tools there - but I cannot? I have to specify every reference as Toolbox::FormatString?

class CHaspException : public CLabeledException
{
public:
    CHaspException(haspStatus status) :
        CLabeledException(FormatString(_T("HASP Error %u: %s"), (unsigned)status, GetHaspErrorMessage(status))),
        m_status(status)
    {
    }

    CHaspException(const char * source, haspStatus status) :
        CLabeledException(FormatString(_T("%hs: HASP Error %u: %s"), source, (unsigned)status, GetHaspErrorMessage(status))),
        m_status(status)
    {
    }

    CHaspException(const char * source, const char * api, haspStatus status) :
        CLabeledException(FormatString(_T("%hs: %hs() returned %u: %s"), source, api, (unsigned)status, GetHaspErrorMessage(status))),
        m_status(status)
    {
    }

    CHaspException(const char * source, const char * api, const CString & args, haspStatus status) :
        CLabeledException(FormatString(_T("%hs: %hs(%s) returned %u: %s"), source, api, args, (unsigned)status, GetHaspErrorMessage(status))),
        m_status(status)
    {
    }

    haspStatus GetStatus() const { return m_status; }

private:
    haspStatus  m_status;
};

This is a simple example, but I can imagine others where there are more diverse references. In fact code which uses the global begin() and end() is supposed to bring the std namespace into scope, but not actually specify it literally - i.e. it should do:

template <typename T> myfun(T & x)
{
  using namespace std;
  if (begin(x) == end(x))...
}

So that std is available for resolving begin/end, but it is not forced (not use std::being(x)).

So, again, it seems crucial that classes be able to pull a namespace into scope, no?

What's the deal, or what is the right way to do this?


Not a duplicate of that question - though that's an excellent and interesting discussion. Here, I'm flummoxed by the need to tell the compiler "allow resolution in this given scope, but allow type-specific lookup to override that" while restricting the scoping of that directive to just my class or header.

In my second example - which is the "best practices" approach as given by the standards body, I cannot do that. I have no valid scope to work with at a header or class declaration level...

Mordachai
  • 9,412
  • 6
  • 60
  • 112
  • 1
    Possible duplicate of [Why can't we declare a namespace within a class?](https://stackoverflow.com/questions/13484387/why-cant-we-declare-a-namespace-within-a-class) – Klaus Mar 09 '18 at 16:50
  • 1
    This could be helpfull, but there are no other solutions than what you are already doing. – Oliv Mar 09 '18 at 16:51
  • Not a duplicate of that question - though that's an excellent and interesting discussion. Here, I'm flummoxed by the need to tell the compiler "allow resolution in this given scope, but allow type-specific lookup to override that" - at least for the second example - which is the "best practices" approach. Outside of the function definition brackets, I cannot do that. I have no valid scope to work with... – Mordachai Mar 09 '18 at 16:54
  • If you just need `begin()` & `end()`, just pull those two into your functions scope `template myfun(T & x) { using std::begin; using std::end; if (begin(x) == end(x))... }` - no need to pull in the entire namespace. Or just use `std::begin()`/`std::end()` fully qualified and forget about `using`. – Jesper Juhl Mar 09 '18 at 16:54
  • @JesperJuhl yes, for all such questions, "if all I need is X, use X" I'm explicitly stating that these are simplified examples of a concept that goes beyond only needing X. – Mordachai Mar 09 '18 at 16:59
  • In other words, your concern is not with `xyz`, it's with `stupidly::long::namespace::that::goes::on::for::ing::forever` – user4581301 Mar 09 '18 at 17:20
  • No, though sure, there's that too. It's more like "I want to not specify the exact namespace of a given identifier, but I want to specify what namespaces to search within for it" - which is useful for avoiding typing, sure, but also avoiding locking into a specific implementation and instead using ADL to find the correct candidate. – Mordachai Mar 09 '18 at 17:45
  • 1
    as a potential fix, if your class is within a namespace, you can use `using` within so that imported names will be confined to that namespace only (not global). its not a *great* idea but it is available – kmdreko Mar 09 '18 at 18:16
  • 1
    Not exactly a duplicate, but [my question](https://stackoverflow.com/q/46168188/8586227) is something of an answer here. – Davis Herring Mar 09 '18 at 23:11
  • @DavisHerring thank you. I could then put the real definition into a detail namespace and just have a publicly scoped wrapper which itself doesn't do any init - and make all out of scope refs explicit in the public wrapper. Not too shabby. :) – Mordachai Mar 12 '18 at 14:57
  • @Mordachai: You can just expose (certain) classes from the implementation with `using`. – Davis Herring Mar 12 '18 at 20:09
  • @DavisHerring as in the class is inside of a details namespace, but then at the library namespace declare a set of using classname? – Mordachai Mar 12 '18 at 21:06
  • 1
    @Mordachai: Exactly. This doesn’t work for templates you want users to specialize, but serves most other purposes. – Davis Herring Mar 13 '18 at 04:38

0 Answers0