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 ++.
source to share
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) ....
source to share
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 ...
source to share
§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 ::
".
source to share
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.
source to share