Is there a better way to express nested namespaces in C++ within the header

前端 未结 11 2450
天涯浪人
天涯浪人 2020-12-13 03:31

I switched from C++ to Java and C# and think the usage of namespaces/packages is much better there (well structured). Then I came back to C++ and tried to use namespaces the

相关标签:
11条回答
  • 2020-12-13 03:46

    [ EDIT: ]
    Since c++17 nested namespaces are supported as a standard language feature (https://en.wikipedia.org/wiki/C%2B%2B17). As of now, this feature is not supported in g++8, but it can be found the in clang++6.0 compiler.


    [ CONCLUSION: ]
    Use clang++6.0 -std=c++17 as your default compilation command. Then everything should work fine - and you will be able to compile with namespace OuterNS::InnerNS1::InnerNS2 { ... } in your files.


    [ ORIGINAL ANSWER: ]
    Since this question is a bit old, I will assume that you have moved on. But for others, who are still looking for an answer, I came up with the following idea:

    (Might I make an advertisement for Emacs here :) ?) Posting an image is far easier, and more readable, than to simply post code. I do not intend to provide a full-flegded anwer of all corner cases, simply I meant to give some inspiration. (I totally support C# and feel that in many cases C++ should adopt some OOP features, since C# is popular mainly due to its compared ease of use).

    0 讨论(0)
  • 2020-12-13 03:48

    No, and please don't do that.

    The purpose of namespaces is primarily resolving conflicts in the global namespace.

    A secondary purpose is local abbreviation of symbols; e.g. a complex UpdateUI method may use an using namespace WndUI to use shorter symbols.

    I'm on a 1.3MLoc project, and the only namespaces we have are:

    • imported external COM libraries (mainly to isolate header conflicts between #import and #include windows.h)
    • One level of "public API" namespaces for certain aspects (UI, DB access etc.)
    • "Implementation Detail" namespaces that are not part of the public API (anonymous namespaces in .cpp's, or ModuleDetailHereBeTygers namespaces in header-only libs)
    • enums are the biggest problem in my experience. They pollute like crazy.
    • I still feel it's entirely too many namespaces

    In this project, class names etc. use a two- or three-letter "region" code (e.g. CDBNode instead of DB::CNode). If you prefer the latter, there's room for a second level of "public" namespaces, but no more.

    Class-specific enums etc. can be members of those classes (though I agree this is not always good, and it's sometimes hard to say whether you should)

    There's rarely need for a "company" namespace either, except if you are having big problems with 3rd party libraries that are distributed as binary, don't provide their own namespace, and can't be easily put into one (e.g. in a binary distribution). Still, in my experience forcing them into a namespace is much easier to do.


    [edit] As per Stegi's follow-up question:

    Ok, so what about Windows::UI::Xaml and Windows::UI::Xaml::Controls::Primitives namespaces in Win8 development? I think Microsoft's usage of namespaces makes sense and it is indeed deeper than just 2 Levels

    Sorry if I wasn't clear enough: Two levels isn't an hard limit, and more isn't intrinsically bad. I just wanted to point out that you rarely need more than two, from my experience, even on a large code base. Nesting deeper or more shallow is a tradeoff.

    Now, the Microsoft case is arguably different. Presumably a much larger team, and all the code is library.

    I'd assume Microsoft is imitating here the success of the .NET Library, where namespaces contribute to the discoverability of the extensive library. (.NET has about 18000 types.)

    I'd further assume that there is an optimal (order of magnitude of) symbols in a namespace. say, 1 doesn't make sense, 100 sounds right, 10000 is clearly to much.


    TL;DR: It's a tradeoff, and we don't have hard numbers. Play safe, don't overdo in any direction. The "Don't do that" comes merely from the "You have problems with that, I'd have problems with that, and I don't see a reason why you'd need it.".

    0 讨论(0)
  • 2020-12-13 03:51

    You can use this syntax:

    namespace MyCompany {
      namespace MyModule {
        namespace MyModulePart //e.g. Input {
          namespace MySubModulePart {
            namespace ... {
              class MyClass;
            }
          }
        }
      }
    }
    
    // Here is where the magic happens
    class MyCompany::MyModule::MyModulePart::MySubModulePart::MyYouGetTheIdeaModule::MyClass {
        ...
    };
    

    Note this syntax is valid even in C++98 and it is almost similar to what is now available in C++17 with nested namespace definitions.

    Happy unnesting!

    Sources:

    • http://seanmiddleditch.com/unnest-c-namespaces/
    • http://www.nuonsoft.com/blog/2017/08/01/c17-nested-namespaces/
    0 讨论(0)
  • 2020-12-13 03:59

    C++17 might simplify nested namespace definition:

    namespace A::B::C {
    }
    

    is equivalent to

    namespace A { namespace B { namespace C {
    } } }
    

    See (8) on namespace page on cppreference:
    http://en.cppreference.com/w/cpp/language/namespace

    0 讨论(0)
  • 2020-12-13 04:03

    Here a quote from Lzz (Lazy C++) docs:

    Lzz recognizes the following C++ constructs:

    namespace definition

    An unnamed namespace and all enclosed declarations are output to the source file. This rule overrides all others.

    The name of a named namespace may be qualified.

       namespace A::B { typedef int I; }
    

    is equivalent to:

       namespace A { namespace B { typedef int I; } }
    

    Of course the quality of sources that depends on such tools is debatable... I would say it's more a curiosity, showing that the syntax disease induced by C++ can take many form (I have mine, too...)

    0 讨论(0)
提交回复
热议问题