Doc. no. | P1094R0 |
Date: | 2018-05-07 |
Project: | Programming Language C++ |
Audience: | Evolution Working Group |
Reply to: | Alisdair Meredith <ameredith1@bloomberg.net> |
Original version of the paper for the 2017 post-Albuquerque mailing.
Inline namespaces are not supported in nested namespace definitiond, and it is surprising that the "obvious" syntax is not supported.
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 }; } } }
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.
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.
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.
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.
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