Namespaced class definition style validity

Summary:

Is there any documentation (like the C ++ standard) to maintain the validity of defining a C ++ class with style:

namespace N { class X; }
class N::X { ... }

      

Details:

We use several styles in some of our corporate codes to define classes:

// n_x.h - style 1
namespace N {
  class X;
}

class N::X {...}

      

and

// n_y.h - style 2
namespace N {
  class Y;
}

namespace N {
  class Y { ... };
}

      

The key difference between class N::X

style 1 and namespace N { class Y {...}...

style 2, i.e. we wrap class Y in style 2 in the namespace.

Both styles seem valid to me (we never had any problems compiling them on VS20xx and Clang), but a colleague questioned if style 1 is valid as a tool we use to analyze our code, misidentifies class X will be part namespaces when using style 1.

I hope someone can provide me with a link to the documentation that shows that style 1 is a valid way to define a class in C ++.

+3


source to share


4 answers


Perhaps this quote from Bjarne Stroustup's book can serve you.

From Chapter 14 The C ++ Programming Language, Fourth Edition :

----- (p. 392)

[...]

14.2.1 Explicit qualification

A member can be declared winthin in the namespace definition and defined later using namespace-name :: principal name notation.

Namespace members must be using these notations:



namespace namespace-name {
   // declarations and definitions
}

      

For example:

namespace Parser {
     double expr(bool); //declaration
     double term(bool);
     double prim(bool);
}

double val = Parser::expr(true); // use

double Parser::expr(bool b) //definition
{
    // ...
}

      

We cannot declare a new namespace member outside the namespace definition using the qualifier syntax (iso.7.3.1.2) ....

+1


source


Yes, style 1 is valid.

[namespace.memdef]/2

:



Members of a named namespace can also be defined outside of that namespace by explicitly qualifying (3.4.3.2) the designated name, provided that the designated object has already been declared in the namespace and the definition appears after the point of declaration in the namespace that encompasses the namespace declaration ...

+4


source


§9 [class] / p11:

If the class-head name contains a nested name specifier, the class specifier refers to a class that was previously declared directly in the class or namespace to which the nested specifier name refers, or to an inline namespace element (7.3.1) of that namespace (i.e. (i.e. not just inherited or injected with a declaration-declaration), but the class specifier must appear in the namespace containing the previous declaration. In such a case, the nested class-head-name specifier does not have to start with the decltype specifier.

class-head-name is a term for the thing that names the class being defined. inested-name-specifier is the default for "everything to the left of ::

, including self ::

".

0


source


From A.8 Classes [gram.class]

:

...
class-specifier:
    class-head { member-specification_opt }

class-head:
    class-key attribute-specifier-seq_opt class-head-name class-virt-specifier_opt
    base-clause_opt class-key attribute-specifier-seq_opt base-clause_opt

class-head-name:
    nested-name-specifier_opt class-name

class-virt-specifier:
    final

class-key:
    class
    struct
    union

      

Thus, between keyword class-key

and is class-name

valid nested-name-specifier

. nested-name-specified

described in A.4 Expressions [gram.expr]

:

nested-name-specifier:
    ::
    type-name ::
    namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier template_opt simple-template-id ::

      

So, namespace-name

are valid in the definition.

0


source







All Articles