Doc. no. P1094R0
Date: 2018-05-07
Project: Programming Language C++
Audience: Evolution Working Group
Reply to: Alisdair Meredith <ameredith1@bloomberg.net>

Nested Inline Namespaces

Table of Contents

  1. Revision History
  2. Introduction
  3. Stating the problem
  4. Propose Solution
  5. Other Directions
  6. Formal Wording
  7. Acknowledgements
  8. References

Revision History

Revision 0

Original version of the paper for the 2017 post-Albuquerque mailing.

1 Introduction

Inline namespaces are not supported in nested namespace definitiond, and it is surprising that the "obvious" syntax is not supported.

2 Stating the problem

While working on the header synopses for several TSes, it is apparent how convenient the nested namespace feature is. However, it is equally surprising that the inline versioning namespace cannot be similarly decalared. For example, in the Concurrency TS v2 it would be nice to specify the <experimental/execution> synopsis as:

namespace std::experimental::inline parallism_v2::execution {
  // 5.7, Unsequenced execution policy
  class unsequenced_policy;

  // 5.8, Vector execution policy
  class vector_policy;

  // 5.10, execution policy objects
  inline constexpr sequenced_policy seq{ unspecified };
  inline constexpr parallel_policy par{ unspecified };
}

Instead, must must open and close namespaces three separate times, essentially rendering the nested namespace feature useless:

namespace std::experimental {
inline namespace parallism_v2 {
namespace execution {
  // 5.7, Unsequenced execution policy
  class unsequenced_policy;

  // 5.8, Vector execution policy
  class vector_policy;

  // 5.10, execution policy objects
  inline constexpr sequenced_policy seq{ unspecified };
  inline constexpr parallel_policy par{ unspecified };
}
}
}

2.1 Impact on the Language

The concern raised is an inconvenient embarrassment, rather than a fundamental flaw. It would be nice to see this fixed, and hopefully should be possible with a minimal investment of time by the committee. If it is not seen as immediately useful, it is probably not worth further committee time to discuss alternative designs.

3 Propose Solution

The proposed solution is fairly simple: allow the inline keyword to optionally precede the identifier naming a namespace at each step of a nested namespace declaration. It is believed that editing the grammar is a sufficient change, as the existing text can be interpreted to have the right meaning after this change too.

3.1 Compatibilty Concerns

The proposed solution is a pure extension where the new syntax was not valid before, and could not show up even in a SFINAE context. There are not expected to be any backwards compatibility concerns.

A fine-grained feature macro is not warranted in this case, as use of the macro to enable the convenience feature would be more work than the convenience returned. The regular __cplusplus macro should suffice for those keep to create a codebase anticipating a future cleanup that can assume this feature once support for older dialects (by that user) is dropped.

4 Other Directions

Given the existing syntax does not support an inline before the namespace keyword for a nested namespace declaration, which is the position required in the grammar for a non-nested namespace declaration, careful consideration was given to supporting this as an option too, if for no other reason than the notion of consistency.

This idea was rejected as potentially confusing. Which namespace is intended to be inline in such cases? The trailing namespace? The leading namespace? All of the namespaces? Requiring the inline keyword to precede the namespace that it inlines cleanly resolves such concerns, so there should be no other syntax supported to introduce such confusion, along with endless style-guide debates.

It was also observed, while drafting this paper, that nested namespaces do not support attributes. That was deemed a separate issue beyond the scope of this paper, and is not a topic the author is motivated to solve himself.

5 Formal Wording

Make the following changes to the specified working paper:

10.3.1 Namespace definition [namespace.def]

namespace-name:
    identifier
    namespace-alias

namespace-definition:
    named-namespace-definition
    unnamed-namespace-definition
    nested-namespace-definition

named-namespace-definition:
    inlineopt namespace attribute-specifier-seqopt identifier { namespace-body }

unnamed-namespace-definition:
    inlineopt namespace attribute-specifier-seqopt { namespace-body }

nested-namespace-definition:
    namespace enclosing-namespace-specifier :: inlineopt identifier  { namespace-body }
    
enclosing-namespace-specifier:
    inlineopt identifier
    enclosing-namespace-specifier :: inlineopt identifier

namespace-body :
    declaration-seqopt