Can I use class scope like a namespace instead of prefixing everything with the class name

Viewed 46

So inside header files I can do

namespace X {
    doThis();
}

and in the implementation file I can do

namespace X {
   doThis() { .... }
}

But if I have a class

class X {
    public:
    doThis();
};

Is it possible for me to do something like this in the implementation file

class X {
    doThis() { .... }
}

instead of X::doThis() { .... }?

1 Answers

There's the "Java hack"¹, where you "inherit" from the class to get its members into your namespace:

class MyUserType : /*protected|private*/ X {

     void foo() {
         doThis(); // works
     }
}

Of course this only works of

  • the class doesn't define additional (non-static) features that interfere when inherited
  • your calling code is in a class that can inherit from the type
  • the derived class is not a template because 2-phase lookup makes things weird again (though you can use using declarations to mitigate them, on a name-by-name basis)

Re: static data members/out of class definition

In the comments you seem to have a problem with brevity of code mostly. Look into

Disclaimer: following examples largely copied from cppreference

  1. inline variables (c++17), which is about namespace level static variables, which also applies to class members:

    enter image description here

  • constexpr/const static member initialization right in the declaration.

    If a static data member of integral or enumeration type is declared const (and not volatile), it can be initialized with an initializer in which every expression is a constant expression, right inside the class definition:

     struct X
     {
         const static int n = 1;
         const static int m{2}; // since C++11
         const static int k;
     };
     const int X::k = 3;
    
  1. constexpr members are even required to have the initializer in the declaration:

    struct X {
        constexpr static int arr[] = { 1, 2, 3 };        // OK
        constexpr static std::complex<double> n = {1,2}; // OK
        constexpr static int k; // Error: constexpr static requires an initializer
    };
    
  2. Note that in some circumstances you may still need out-of-class definitions, but without the initializer:

    If a const non-inline (since C++17) static data member or a constexpr static data member (since C++11)(until C++17²) is odr-used, a definition at namespace scope is still required, but it cannot have an initializer. A definition may be provided even though redundant (since C++17).

    struct X {
        static const int n = 1;
        static constexpr int m = 4;
    };
    const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used
    const int X::n;             // … so a definition is necessary
    constexpr int X::m;         // … (except for X::m in C++17)
    

¹ for the longest time Java didn't have enumerations, so you'd define static constants in a base class an "inherit" from it to get the constants.

² If a static data member is declared constexpr, it is implicitly inline and does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated.

Related