How to alias the global namespace in C++11
Asked Answered
D

2

12

Short Form: How can I define an alias for the root (global) namespace in C++11 ? It might look like

namespace root_namespace = :: ;

where the scope resolution operator in its naked form above is a place holder for some handle of the global namespace. I read in the GCC Internals Manual that

...The root of the [compiler's] entire intermediate representation is the variable global_namespace. This is the namespace specified with :: in C++ source code... The name of the global namespace is ::, even though in C++ the global namespace is unnamed.

PS EDIT: to respondents to-date, I appended a painfuly long form to address some concerns after the following long form, since it may clarify some things. And followers, if you see us talking at rather than to each other, dig in.


Long Form: An example of its potential use follows. If unsatisfactory, then yes, this is an academic question ; see the painfully long form that follows this one.

Imagine that your boss barges in one day and says, "I just read a book about post-positivism. Get rid of namespace ObjectiveReality." In the code below, 'all' you have to do is omit the lines I've marked like /* -> */ this /* <- */. You can do that for intermediate levels of nesting currently ; however, I am uncertain how to define the global-scope namespace current_authority to allow simple elision of the first non-global namespace.

#include <iostream>
#include <iomanip>


// ...
using cat_is_alive = std::true_type ; // because I like cats
using cat_is_alive = ::cat_is_alive ; // seems to work, see `g++ -v` below
// ...


// ASIDE: I originally had `namespace higher_authority = COMPILER ;` as a comment, but changed it for simpler chaining closure

// The next two lines are the crux of my question...

namespace higher_authority = global_namespace ;
namespace current_authority = global_namespace ; // a.k.a. the naked ::

// If the above two lines defined aliases for the (unnamed) global namespace, then the suggested elisions/replacements work...

/* -> */
namespace ObjectiveReality {
/* <- */
// Simplest fix: replace with `using ObjectiveReality = current_authority ;`
//   (Otherwise, a few other changes are necessary)

    namespace higher_authority = current_authority ;
    namespace current_authority = ObjectiveReality ;

    using cat_is_alive = higher_authority::cat_is_alive ;

    namespace EntangledObserver {

        namespace higher_authority = current_authority ;
        namespace current_authority = EntangledObserver ;

        using cat_is_alive = higher_authority::cat_is_alive ;
    } ;
/* -> */
} ;
/* <- */


int main( int argc, char** argv ) {

    std::cout
        << "It is "
        << ObjectiveReality::EntangledObserver::cat_is_alive::value
       << " that the cat is alive." << std::endl ;

    return 0 ;
}


// EOF

In case compiler info is needed:

$ g++ -std=c++11 -v

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.7/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.2-11precise2' 
--with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs 
--enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 
--enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib 
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib
--enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug 
--enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin
--enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686
--with-multilib-list=m32,m64 --with-tune=generic --enable-checking=release 
--build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Thread model: posix
gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2) 

PAINFULLY LONG FORM: as a response to some answers about "start from a nested namespace," note that 'HOME!' is inaccessible, and that I may not have the luxury of hand-picking namespaces in a team.

//
// alice.cpp
//


#include <iostream>
#include <type_traits>


/////
///// The Setup
/////

//
// One-and-a-half macros
//

// BOO! Get rid of this case!
#define ENABLE_SUBSPACE_1( namespace_name ) \
    namespace namespace_name { \
    namespace last_namespace = ::namespace_name ; \
    namespace this_namespace = ::namespace_name ;

// YEAH! Instead, define 'namespace this_namespace = :: ;' and then...
#define ENABLE_SUBSPACE( namespace_name ) \
    namespace namespace_name { \
    namespace last_namespace = this_namespace ; \
    namespace this_namespace = last_namespace::namespace_name ;

//
// Some characters
//

struct dorothy {
    static constexpr auto obvious_statement = "There's no place like " ;
} ;

struct rabbit {
    template< typename T >
    static constexpr char const* says( T ) {
        return T::value ? "I'm late!" : "I'm late, but I ditched that addled girl." ;
    }
} ;

struct alice {

    using blue_pill = std::false_type ;
    static constexpr auto where_am_i = "HOME!" ;
} ;


/////
///// The Central Structure
/////

ENABLE_SUBSPACE_1( oxford_england ) // {

    using has_strangers_with_candy = std::true_type ;

    struct alice {
        using blue_pill = this_namespace::has_strangers_with_candy ;
        static constexpr auto where_am_i = "Uncle Charles' picnic blanket." ;
    } ;

ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
    using has_strangers_with_candy = std::false_type ; ///// Different...
ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
    struct alice { ///// Different...
        using blue_pill = has_strangers_with_candy ;
        static constexpr auto where_am_i = "needing a fix." ;
    } ;
ENABLE_SUBSPACE( rabbit_hole ) // {
    struct rabbit { using is_late = typename alice::blue_pill ; } ;
    struct alice : last_namespace::alice { ///// Different...
        static constexpr auto where_am_i = "an empty rabbit hole." ;
    } ;
} ; // END rabbit_hole
} ; // END rabbit_hole
} ; // END rabbit_hole
} ; // END rabbit_hole
} ; // END rabbit_hole
} ; // END rabbit_hole
} ; // END oxford_england


/////
///// Snarky Output
/////

int main( int argc, char** argv ) {

    std::cout << std::endl
        << dorothy::obvious_statement
        << alice::where_am_i
        << std::endl ; // There's no place like HOME!

    std::cout
        << dorothy::obvious_statement
        << oxford_england::rabbit_hole::rabbit_hole::rabbit_hole::rabbit_hole::rabbit_hole::alice::where_am_i
        << std::endl ; // There's no place like needing a fix.

    std::cout
        << dorothy::obvious_statement
        << oxford_england::rabbit_hole::rabbit_hole::rabbit_hole::rabbit_hole::rabbit_hole::rabbit_hole::alice::where_am_i
        << std::endl ; // There's no place like an empty rabbit hole.

    std::cout << std::endl
        << rabbit::says(
            oxford_england::
                rabbit_hole::
                    rabbit_hole::
                        rabbit_hole::
                            rabbit_hole::
                                rabbit_hole::rabbit::is_late()
        ) << std::endl ; // I'm late!
    std::cout
        << rabbit::says(
            oxford_england::
                rabbit_hole::
                    rabbit_hole::
                        rabbit_hole::
                            rabbit_hole::
                                rabbit_hole:: // NOTE : alice::blue_pill is false_type
                                    rabbit_hole::rabbit::is_late() // ... not this time ; Alice is crashing.
        ) << std::endl ; // I'm late, but I ditched that addled girl.

    std::cout << std::endl
        << dorothy::obvious_statement
        << oxford_england::
                rabbit_hole:: // 1
                    rabbit_hole:: // 2
                        rabbit_hole:: // 3
                            rabbit_hole:: // 4
                                rabbit_hole:: // 5
                                    rabbit_hole:: // rabbit_hole #6
                                last_namespace:: // rabbit_hole #5
                            last_namespace:: // rabbit_hole #4
                        last_namespace:: // rabbit_hole #3
                    last_namespace:: // rabbit_hole #2
                last_namespace:: // rabbit_hole #1
            last_namespace::alice::where_am_i // oxford_england
        << std::endl ; // There's no place like Uncle Charles' picnic blanket.
    std::cout
        << dorothy::obvious_statement
        << oxford_england::
                rabbit_hole::
                    rabbit_hole::
                        rabbit_hole::
                            rabbit_hole::
                                rabbit_hole::
                                    rabbit_hole::
                                last_namespace::
                            last_namespace::
                        last_namespace:: // 3
                    last_namespace:: // 2
                last_namespace:: // 1
            last_namespace:: // oxford
        last_namespace::alice::where_am_i // not the global namespace!
        << ".. but I'd rather be " << ::alice::where_am_i // the global namespace.
        << std::endl ; // There's no place like Uncle Charles' picnic blanket... but I'd rather be HOME!

    std::cout << std::endl ;
    return 0 ;
}


/////
///// EOF
/////


/* Compiled with:
    `g++ -std=c++11 -o alice alice.cpp`
*/

/* Output of `alice` :

There's no place like HOME!
There's no place like needing a fix.
There's no place like an empty rabbit hole.

I'm late!
I'm late, but I ditched that addled girl.

There's no place like Uncle Charles' picnic blanket.
There's no place like Uncle Charles' picnic blanket... but I'd rather be HOME!

*/
Deranged answered 7/2, 2013 at 22:45 Comment(5)
English please. The word is "colon".Channel
Why can't you just add using namespace ObjectiveReality; to your global scope?Channel
+1 for a curiously philosophical take on C++ namespaces.Janenejanenna
@Kerrek - I picked up the PAAMAYIM_NEKUDOTAYIM from a PHP error I got a few times. It's what the interpreter called it; vive la différence, oy!Deranged
Send the boss to a shrink. ;-) (Clearly I have a firm position on the issue of positivism.)Gaidano
L
2

I do not think you can alias the global namespace.

The standard defines a namespace alias with :: called out explicitly instead of treating it like just another namespace name:

7.3.2   Namespace alias
A namespace-alias-definition declares an alternate name for a namespace according to the following grammar:
namespace-alias:
    identifier 
namespace-alias-definition:
    namespace identifier = qualified-namespace-specifier ;
qualified-namespace-specifier:
    ::_opt nested-name-specifier_opt namespace-name

Note that :: is opt (optional), but the namespace-name is not.

However, couldn't you just use something other than the global namespace as the start of your namespace stack and still follow the pattern you've outlined?

Also note that your example does in fact need a couple additional lines edited when you remove ObjectiveReality:

namespace current_authority = ObjectiveReality ;

and:

<< ObjectiveReality::EntangledObserver::cat_is_alive::value

Here's what your example looks like using namespace "something" instead of the global namespace as the root of your namespace stack.

#include <iostream>
#include <iomanip>


// ...                                                                                                                                                                                                                                                                                                                                                                    
namespace something {
  using cat_is_alive = std::true_type ; // because I like cats                                                                                                                                                                                                                                                                                                            
}
using namespace something;
// ...                                                                                                                                                                                                                                                                                                                                                                    


// ASIDE: I originally had `namespace higher_authority = COMPILER ;` as a comment, but changed it for simpler chaining closure                                                                                                                                                                                                                                            

// The next two lines are the crux of my question...                                                                                                                                                                                                                                                                                                                      

namespace higher_authority = something;
namespace current_authority = something;                                                                                                                                                                                                                                                                                                         

// If the above two lines defined aliases for the (unnamed) global namespace, then the suggested elisions/replacements work...                                                                                                                                                                                                                                            

/* -> */
namespace ObjectiveReality {
  /* <- */
  // Simplest fix: replace with `using ObjectiveReality = current_authority ;`                                                                                                                                                                                                                                                                                            
  //   (Otherwise, a few other changes are necessary)                                                                                                                                                                                                                                                                                                                     

  namespace higher_authority = current_authority ;
  namespace current_authority = ObjectiveReality ;

  using cat_is_alive = higher_authority::cat_is_alive ;

  namespace EntangledObserver {

    namespace higher_authority = current_authority ;
    namespace current_authority = EntangledObserver ;

    using cat_is_alive = higher_authority::cat_is_alive ;
  } ;
  /* -> */
} ;
/* <- */


int main( int argc, char** argv ) {

  std::cout
    << "It is "
    << ObjectiveReality::EntangledObserver::cat_is_alive::value
    << " that the cat is alive." << std::endl ;

  return 0 ;
}


// EOF
Lewison answered 8/2, 2013 at 0:14 Comment(4)
you called me out. I actually rewrote cat_is_alive as a type trying to obfuscate my iniquity ; I will have to mull your candidate answer over, thanks for both the example and grammar! Meantime: is there a legit existential reason to disallow a global namespace alias ?Deranged
Still mulling - but like, there's a hole in the bucket. From Soverman above, "...couldn't you just use something other than the global namespace as the start of your namespace stack and still follow the pattern you've outlined?" My grand scheme is to fix the n = 1 base case. n => n+1 is great, but levels-of-abstraction isn't the solution here, is it?Deranged
I do not think there is any existential[ist] reason to prevent aliasing the global namespace. As far as I can tell that's just the way the language is defined. Sometimes c++ is a bit absurd[ist]. Can you explain why using a named namespace instead of the global namespace as your n=1 base case does not work for your scenario? I didn't follow your levels-of-abstraction concern.Lewison
I think perhaps it's time for a new question. The original question was clear: "how can I alias the global namespace?", and has a clear answer: "you can't". Now I think the new question is something like "how can I emulate a stack-like namespace structure under certain constraints on what code I am allowed to edit". To get a good answer to that question I think you're going to have to be more explicit about your constraints due to being on a team and being able to modify only some of the code. Your painfully long form seems to work except for violating those constraints.Lewison
D
1

I'm not aware of a way to directly alias the default namespace, but as a workaround you might use a macro (assuming you're willing to live with the macro's name colliding with unrelated symbols).

#define root_namespace

Usage:

root_namespace::cat_is_alive

As Mooing Duck correctly points out, this hack won't work with using clauses.

Danner answered 8/2, 2013 at 21:12 Comment(1)
This is clever, but... using namespace root_namespace;Selfassured

© 2022 - 2024 — McMap. All rights reserved.