N4196 / CWG 1657 / EWG 113
Richard Smith

Attributes for namespaces and enumerators


When N3394 introduced the [[deprecated]] attribute to C++, there was a desire for it to apply to:

However, attributes are not permitted on enumerators nor on namespaces. In response, CWG issue 1657 and EWG issue 113 were filed and received favourably. This paper proposes resolving these issues by allowing attributes to be specified on enumerators and namespaces, and extends the [[deprecated]] attribute to apply to these entities, as was originally intended.


Location of attributes on enumerators

Once we decide to allow attributes on enumerators, we must answer one question: are attributes written before or after the name of the enumerator? There are no grammar ambiguities in either location, so this is a free choice. Analysis of the grammar and prior papers results in a simple rule: attributes are written either

Since an enumerator-definition is not a declaration nor a statement, the most natural place to put the attribute-specifier-seq is after the identifier:
enum E {
  foobar = 0,
  foobat [[deprecated]] = foobar

This choice also preserves the ability to lay out enumerations with the enumerator names in a column.

Attributes on namespaces

Namespaces can be repeatedly declared and can be reopened, and thus can have different attributes in different translation units or in different locations in the same translation unit. Likewise, namespaces can be anonymous or inline, and some namespace attributes might be problematic in such cases. Nonetheless, this paper proposes allowing attributes in all such cases, with no inherent restrictions; the specification for each individual attribute that can appertain to a namespace should cover how to handle any problematic cases. This is the status quo for attributes on other entities.

For consistency with classes and enumerations, the natural location for the attribute-specifier-seq is after the namespace keyword.

Meaning of deprecating a namespace

Following the lead of N3394, this paper provides no normative requirements on the effect of deprecating an entity. For an inline namespace, this paper suggests that implementations might wish to consider issuing a warning only if the name of the namespace is used (and not if entities within that namespace are named as members of a surrounding namespace). This allows a library author to discourage its clients from naming an inline namespace directly, while still allowing access to its members. With this approach, deprecating an unnamed namespace would have no effect, and implementations may wish to issue a warning on such a construct.

Proposed Wording

Change in 7.2 (dcl.enum) paragraph 1:

        identifier attribute-specifier-seqopt
The optional attribute-specifier-seq in the enum-head and the opaque-enum-declaration appertains to the enumeration; the attributes in that attribute-specifier-seq are thereafter considered attributes of the enumeration whenever it is named. [...]

Change in 7.2 (dcl.enum) paragraph 2:

[...] The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required. An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression. If the first enumerator has no initializer, the value of the corresponding constant is zero. An enumerator-definition without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator by one. [ Example: … ] The optional attribute-specifier-seq in an enumerator appertains to that enumerator.

Change in 7.3 (namespace.def) paragraph 1:

        inlineopt namespace attribute-specifier-seqopt identifier { namespace-body }
        inlineopt namespace attribute-specifier-seqopt original-namespace-name { namespace-body }
        inlineopt namespace attribute-specifier-seqopt { namespace-body }

Add a new paragraph after 7.3 (namespace.def) paragraph 7:

The optional attribute-specifier-seq in a namespace-definition appertains to the namespace being defined or extended.

Change in 7.6.5 (dcl.attr.deprecated) paragraph 2:

The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, a namespace, an enumeration, an enumerator, or a template specialization.