RFC: Class Namespace

350 views
Skip to first unread message

Matthew Woehlke

unread,
Nov 19, 2015, 2:43:29 PM11/19/15
to std-pr...@isocpp.org
I've written up a draft proposal for a "class namespace" feature based
on the recent thread¹. In short, it introduces the new syntax:

template <...> // optional
namespace class Foo
{
Foo(...) { ... }
void foo(...) { ... }
}

...which is equivalent to:

template <...> Foo<...>::Foo(...) { ... }
template <...> void Foo<...>::foo(...) { ... }

Basically, it allows one to "hoist" the class name (along with template
specifications) out of a collection of out-of-line class member
definitions and into a block scope. The class name (and template bits)
are then implicitly applied to all definitions within said scope.

I'm attaching the current version for you lazy people that like to see
it in-line :-). You can also find the up to date version (with pretty
HTML formatting) at
https://github.com/mwoehlke/cpp-proposals/blob/Pxxx-class-namespace/PXXXX%20Class%20Namespace.rst.

Comments appreciated, especially pointing out anything I've missed.


https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/e0_ceXFQX-A)

--
Matthew
PXXXX Class Namespace.rst

Bjorn Reese

unread,
Nov 19, 2015, 3:07:23 PM11/19/15
to std-pr...@isocpp.org
What about template specialization? Can I have a general template
class definition, and then use different specialized class namespaces
for it?

Miro Knejp

unread,
Nov 19, 2015, 3:18:45 PM11/19/15
to std-pr...@isocpp.org
(1) Considering the syntax: we have contextual keywords now.

template<...> // optional
class Foo implementation
{
...
}

Just in case people are opposed to "namespace" (or any other existing
keyword that doesn't "quite fit").

(2) Why the necessity to repeat the template arguments in
template<class T>
namespace class B<T> { }
?

The leading template declaration should be unambiguous and IMHO the
syntax should be as analogous to a normal class definition as possible,
including the use for (partial) template specializations

template<class T>
namespace class B { void bar() { } } // implement template<class T> void
B<T>::bar()

template<>
namespace class B<int> { void bar() { } } // implement void B<int>::bar()

The latter requires a preceding definiton of template<> class B<int> to
be well-formed.

Matthew Woehlke

unread,
Nov 19, 2015, 3:38:10 PM11/19/15
to std-pr...@isocpp.org
Do you mean like this?

template <> namespace class specialized<int, 5>
{
...
}

...?

Yes, of course you can. The "rule" is that this:

[<template_args>] namespace class <name> {
[<type>] <member_name><...>
}

...is equivalent to this:

[<template_args>] [<type>] <name>::<member_name><...>

--
Matthew

Russell Greene

unread,
Nov 19, 2015, 3:39:11 PM11/19/15
to std-pr...@isocpp.org

I really like it. One question I would have is how this works with template specializations.

I would propose it just looks like the current class syntax, just with the template parameters after the class.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

Nicol Bolas

unread,
Nov 19, 2015, 3:43:25 PM11/19/15
to ISO C++ Standard - Future Proposals

OK, so what does this mean:

class implementation
{
};

Is `implementation` here an identifier or the contextual keyword?

Also, what about the final semicolon? The nice thing about `class namespace` is that, since it has `namespace` there, you can argue that you don't need a semicolon. But since this looks exactly like a class definition, people will be expecting the semicolon.
 

Just in case people are opposed to "namespace" (or any other existing
keyword that doesn't "quite fit").

(2) Why the necessity to repeat the template arguments in
template<class T>
namespace class B<T> { }
?

So that you can have template specialization syntax:

template<typename T>
class B
{
};

template<>
class B<X>
{
};

template<typename T>
namespace class B<T>
{
}

template<>
namespace class B<X>
{
}

The leading template declaration should be unambiguous and IMHO the
syntax should be as analogous to a normal class definition as possible,
including the use for (partial) template specializations

No, it should not be analogous to a class definition. "Normal class definitions" can add members; these declarations cannot. "Normal class definitions" can declare access classes; these declarations cannot.

This is not a normal class definition, and attempting to make it look like it is is not a good idea.

Matthew Woehlke

unread,
Nov 19, 2015, 3:56:18 PM11/19/15
to std-pr...@isocpp.org
On 2015-11-19 15:19, Miro Knejp wrote:
> (1) Considering the syntax: we have contextual keywords now.
>
> template<...> // optional
> class Foo implementation
> {
> ...
> }
>
> Just in case people are opposed to "namespace" (or any other existing
> keyword that doesn't "quite fit").

That could work. Thanks; added to the 'alternative syntaxes' list.

> (2) Why the necessity to repeat the template arguments in
> template<class T>
> namespace class B<T> { }
> ?

Why do you have to repeat them in C++98? I guess you can have this:

template <typename T> Foo::foo(...) { ... }
// Is that Foo<T>::foo or Foo::foo<T>?

...but it seems like the compiler would already know that (recall that
Foo::foo(...) must have been declared already since it is a class
member). So I wonder if there is some reason I am missing why this could
be an issue. However, I added it to the Possible Additions section.

> The leading template declaration should be unambiguous and IMHO the
> syntax should be as analogous to a normal class definition as possible,
> including the use for (partial) template specializations
>
> template<class T>
> namespace class B { void bar() { } } // implement template<class T> void
> B<T>::bar()
>
> template<>
> namespace class B<int> { void bar() { } } // implement void B<int>::bar()
>
> The latter requires a preceding definiton of template<> class B<int> to
> be well-formed.

Why? I can partially specialize a member without partially specializing
the whole class. Why would class name scope suddenly add that requirement?

--
Matthew

Russell Greene

unread,
Nov 19, 2015, 4:01:46 PM11/19/15
to std-pr...@isocpp.org

I think that it shouldn't look like a regular class definition for the reasons above.

It could become really misleading to the programmers that have to learn about this stuff.

Then again, the namespace class idea isn't exactly intuitive either, but at least it doesn't feel like you can declare stuff.

PS sorry for emailing the template specialization question after it had already asked. I wrote it then sent it later.


Matthew Woehlke

unread,
Nov 19, 2015, 4:09:26 PM11/19/15
to std-pr...@isocpp.org
On 2015-11-19 15:43, Nicol Bolas wrote:
> OK, so what does this mean:
>
> class implementation
> {
> };
>
> Is `implementation` here an identifier or the contextual keyword?

Identifier. The context of the contextual keyword is "following the
class name".

Note:

class final {}; // class named "final"
class A final {}; // class "A" which cannot be subclassed

...so there's precedent already.

> On Thursday, November 19, 2015 at 3:18:45 PM UTC-5, Miro Knejp wrote:
>> (2) Why the necessity to repeat the template arguments in
>> template<class T>
>> namespace class B<T> { }
>> ?
>
> So that you can have template specialization syntax:
>
> template<typename T>
> class B
> {
> };
>
> template<>
> class B<X>
> {
> };
>
> template<typename T>
> namespace class B<T>
> {
> }
>
> template<>
> namespace class B<X>
> {
> }

...but this can be *optional*. The compiler knows that template
arguments are supposed to be present. If they aren't, is there a problem
defaulting to the "obvious" arguments?

>> The leading template declaration should be unambiguous and IMHO the
>> syntax should be as analogous to a normal class definition as possible,
>> including the use for (partial) template specializations
>
> No, it should not be analogous to a class definition. "Normal class
> definitions" can add members; these declarations cannot. "Normal class
> definitions" can declare access classes; these declarations cannot.

Right. It should act more like a namespace (except that, again, you
can't add things).

> This is not a normal class definition, and attempting to make it look like
> it is is not a good idea.

Agreed. (And on that note, I'll point out that access specifiers in here
are not permitted.)

--
Matthew

Miro Knejp

unread,
Nov 19, 2015, 4:09:36 PM11/19/15
to std-pr...@isocpp.org
class final
{
};

Is "final" here an identifier or the contextual keyword?

Same rules apply. Before you start yelling "anonymous class": how exactly would you re-open the scope of an anonymous class without resolving to decltype?

Also, what about the final semicolon? The nice thing about `class namespace` is that, since it has `namespace` there, you can argue that you don't need a semicolon. But since this looks exactly like a class definition, people will be expecting the semicolon.
Make it optional or wait for feedback from more than 2 people. I didn't say I dislike "namespace" I just reminded of a second approach in case the keyword re-use falls on deaf ears and should be mentioned in the proposal's discussion as a viable alternative.

 

Just in case people are opposed to "namespace" (or any other existing
keyword that doesn't "quite fit").

(2) Why the necessity to repeat the template arguments in
template<class T>
namespace class B<T> { }
?

So that you can have template specialization syntax:
Did you just not bother reading he rest of my reply?

template<typename T>
class B
{
};

template<>
class B<X>
{
};

template<typename T>
namespace class B<T>
{
}

template<>
namespace class B<X>
{
}

The leading template declaration should be unambiguous and IMHO the
syntax should be as analogous to a normal class definition as possible,
including the use for (partial) template specializations

No, it should not be analogous to a class definition. "Normal class definitions" can add members; these declarations cannot. "Normal class definitions" can declare access classes; these declarations cannot.

This is not a normal class definition, and attempting to make it look like it is is not a good idea.
Why? By making the introductory template definition as close as possible to the actual definiton people don't have to learn a completely new grammar "Do I have to put the template parameter here or not? Why do I have to here but not there? Oh C++ is so inconsistent and stupid". The additional keyword already tells them it's something different.

template<class T> class B { };
template<class T> namespace class B { }

template<> class B<X> { };
template<> namespace class B<X> { }

template<class T, class U> class C { };
template<class T, class U> namespace class C { }

template<class T> class C<T, X> { };
template<class T> namespace class C<T, X> { }

It's consistent so people can use the grammar they already know and understand instead of inventing new rules which unnecessarily complicate the proposal and user experience.

Matthew Woehlke

unread,
Nov 19, 2015, 4:21:44 PM11/19/15
to std-pr...@isocpp.org
On 2015-11-19 16:10, Miro Knejp wrote:
> class final
> {
> };

(Heh... beat you to it :-), though not by enough you would have seen my
reply before sending yours.)

> Is "final" here an identifier or the contextual keyword?
>
> Same rules apply. Before you start yelling "anonymous class": how
> exactly would you re-open the scope of an anonymous class without
> resolving to decltype?

Weeeeelll....

class { void none(); } x;
void decltype(x)::none() {}

...so:

class decltype(x) implementation
{
void none() { ... }
}

...which, yeah, uses decltype. The first example is legal, though, so
the second one would also be legal per the proposal. And, yeah, don't
see a problem with the contextual keyword syntax for doing it since as
you note you have to name the class *somehow*.

> Am 19.11.2015 um 21:43 schrieb Nicol Bolas:
>> Also, what about the final semicolon? The nice thing about `class
>> namespace` is that, since it has `namespace` there, you can argue that
>> you don't need a semicolon. But since this looks exactly like a class
>> definition, people will be expecting the semicolon.
>
> Make it optional or wait for feedback from more than 2 people.

IMHO, it should be optional. Consider:

namespace { ... }; // legal today

(So, basically, if we don't require it, it's implicitly optional because
a stray ';' at global scope is already permitted.)

--
Matthew

Miro Knejp

unread,
Nov 19, 2015, 4:31:31 PM11/19/15
to std-pr...@isocpp.org
Am 19.11.2015 um 21:56 schrieb Matthew Woehlke:
> On 2015-11-19 15:19, Miro Knejp wrote:
>> (1) Considering the syntax: we have contextual keywords now.
>>
>> template<...> // optional
>> class Foo implementation
>> {
>> ...
>> }
>>
>> Just in case people are opposed to "namespace" (or any other existing
>> keyword that doesn't "quite fit").
> That could work. Thanks; added to the 'alternative syntaxes' list.
Another minor nitpick. From a pure "English language" point of view
"class namespace" is more accurate than "namespace class" (since you're
opening the name space of a class, not a class that is a namespace).
Both are currently ill-formed so I guess it's just a matter of preference.
>
>> (2) Why the necessity to repeat the template arguments in
>> template<class T>
>> namespace class B<T> { }
>> ?
> Why do you have to repeat them in C++98? I guess you can have this:
>
> template <typename T> Foo::foo(...) { ... }
> // Is that Foo<T>::foo or Foo::foo<T>?
>
> ...but it seems like the compiler would already know that (recall that
> Foo::foo(...) must have been declared already since it is a class
> member). So I wonder if there is some reason I am missing why this could
> be an issue. However, I added it to the Possible Additions section.
Disambiguation between Foo::foo<T>() and Foo<T>::foo(). Granted the
compiler should know the difference but the repetition provides more
context for lookup. I suspect it's for historical reasons since the
concepts proposal allows getting rid of "template" completely in many
circumstances.
>
>> The leading template declaration should be unambiguous and IMHO the
>> syntax should be as analogous to a normal class definition as possible,
>> including the use for (partial) template specializations
>>
>> template<class T>
>> namespace class B { void bar() { } } // implement template<class T> void
>> B<T>::bar()
>>
>> template<>
>> namespace class B<int> { void bar() { } } // implement void B<int>::bar()
>>
>> The latter requires a preceding definiton of template<> class B<int> to
>> be well-formed.
> Why? I can partially specialize a member without partially specializing
> the whole class. Why would class name scope suddenly add that requirement?
>
Ok, you're right. I can sepcialize B<int>::bar() without defining B<int>
so I guess that would be equally allowed. I think it's important to keep
in mind that as currently presented the proposal is only convenience
syntax that doesn't change existing semantics.

Matthew Woehlke

unread,
Nov 19, 2015, 4:51:38 PM11/19/15
to std-pr...@isocpp.org
On 2015-11-19 16:32, Miro Knejp wrote:
> Am 19.11.2015 um 21:56 schrieb Matthew Woehlke:
>> On 2015-11-19 15:19, Miro Knejp wrote:
> Another minor nitpick. From a pure "English language" point of view
> "class namespace" is more accurate than "namespace class" (since you're
> opening the name space of a class, not a class that is a namespace).
> Both are currently ill-formed so I guess it's just a matter of preference.

See my previous reply¹ to the original thread where I explained why I'm
okay using "namespace" in the first place. To whit, I consider
"namespace" the verb, "<name of class>" the noun, and "class" an
adjective. IOW, "open blue door" vs. "blue open door".

However I'm not strongly wedded to either. The intent is to leave it to
in-person discussion to make this determination.

http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/22734)

> I think it's important to keep
> in mind that as currently presented the proposal is only convenience
> syntax that doesn't change existing semantics.

Exactly :-). (If you check the updated version, I added a
"Specification" section that spells it out as an equivalence transform.)

--
Matthew

Péter

unread,
Nov 20, 2015, 7:42:38 AM11/20/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
Couple of suggestions:

Please consider the use of inner types, too (like the enum E in the below example).  Also, you mention using the bare type B (instead of B<T>) in declarations as a possible addition, but I believe this should be a required feature.   In my opinion, the rules should be such that a "namespace class" definition would look and act the same as an inline definition, with all the name-lookup and other relevant rules applied the same way.  That is, the following example should work:

// in-line definition:
template <typename T>
struct B {
enum E { E1, E2 };

B& operator=(const B& other) {
return *this;
}
void foo(E e) {
}
};

equivalent definition using "namespace class":

// interface
template <typename T>
struct B {
enum E { E1, E2 };
B& operator=(const B& other);

void foo(E e);
};

// implementation
template <typename T>
namespace struct B {
B& operator=(const B& other) {
return *this;
}
void foo(E e) {
}
};



I understand that specifying the exact semantics this way is a bit more work, and (maybe) it's harder to implement, too, but I believe this way we can achieve much better uniformity with the current practice of inline definition.

regards,
mitch





Matthew Woehlke

unread,
Nov 20, 2015, 9:50:29 AM11/20/15
to std-pr...@isocpp.org
On 2015-11-20 07:42, Péter wrote:
> Couple of suggestions:

What's your actual, full name? Your e-mail headers say "Péter" and your
sign-off says "mitch". I'd like to credit you in the proposal (unless
you'd rather I don't), and am wondering how you would like to be credited...

> Please consider the use of inner types, too (like the enum E in the below
> example). Also, you mention using the bare type B (instead of B<T>) in
> declarations as a possible addition, but I believe this should be a
> required feature. In my opinion, the rules should be such that a
> "namespace class" definition would look and act the same as an inline
> definition, with all the name-lookup and other relevant rules applied the
> same way.

I think I see what you are saying. Note that the example you gave
(elided) would work anyway (w.r.t. 'E' anyway), because it appears as a
parameter to the function. It would matter if 'E' was the return type,
because you would ordinarily (i.e. today) have to qualify it there as
B::E. IIUC, you want to be able to write just 'E', correct?

--
Matthew

Péter Radics

unread,
Nov 20, 2015, 10:04:54 AM11/20/15
to std-pr...@isocpp.org
Hello,

   My full name is Péter Radics.  Thanks for the credits :)

I didn't check your original rules fully regarding the inner types so I didn't realize it'd work already (sorry :), I just noticed that you didn't mention inner / nested types and wanted to make a note about that, but indeed, my example would've been better with foo() taking E and also returning E, just to make it clear that it should work without extra qualification there, too.

To sum it up: I'd like "class namespace" to work exactly like inline definitions, that is, if you yank all the inline definitions from an existing class and paste them in a "class namespace", it should Just Work (TM). (keeping forward declarations in the class declaration of course).

One other note: I prefer "class namespace A" over "namespace class A", but that's really minor, I'd be happy with either.

Another more important note: you mentioned that this facility is not designed to add new (private) functions / types / etc, which is understandable, and probably the best approach to get this going, but I think we should somehow keep the door open for future proposals to extend this feature with "real private" methods and "real private" types: it would be really nice to allow introducing new types (internal to the class implementation) and even new private methods (again, internal to the class implementation) into this class namespace.

Oh, and you didn't mention that this class namespace can be re-opened multiple times or not.  I think it'd be worth mentioning that it would work like real namespaces regarding reopening: think about one class namespace in the header for inline definitions, and another class namespace ("reopening") in the cpp file containing out-of-line definitions.  Hope this makes sense :)

Thanks for picking this up, hope you can get it accepted!

regards,
mitch


--

---
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/MPFsRM9qQm0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

Matthew Woehlke

unread,
Nov 20, 2015, 10:32:48 AM11/20/15
to std-pr...@isocpp.org
On 2015-11-20 10:04, Péter Radics wrote:
> Hello,
>
> My full name is Péter Radics. Thanks for the credits :)
>
> I didn't check your original rules fully regarding the inner types so I
> didn't realize it'd work already (sorry :), I just noticed that you didn't
> mention inner / nested types and wanted to make a note about that, but
> indeed, my example would've been better with foo() taking E and also
> returning E, just to make it clear that it should work without extra
> qualification there, too.

No worries; I figured out what you intended, and I agree that we really
ought to do name look-up that way. I've updated the proposal
accordingly. Thanks for pointing this out!

> Another more important note: you mentioned that this facility is not
> designed to add new (private) functions / types / etc, which is
> understandable, and probably the best approach to get this going, but I
> think we should somehow keep the door open for future proposals to extend
> this feature with "real private" methods and "real private" types: it would
> be really nice to allow introducing new types (internal to the class
> implementation) and even new private methods (again, internal to the class
> implementation) into this class namespace.

Agreed on all points. I don't think anything needs to be said to that
effect; if we decide to allow that in the future (though, to be honest
my impression is that there is a lot of resistance to such changes) it
would just be adding new features.

It's off topic, but I'll note that one probable non-starter for such
features is that it breaks encapsulation. Yeah, it's sort of a catch-22.
On the one hand, the whole *point* is to not mention the private bits in
the header. On the other, if you don't, how do you prevent just anyone
from adding new privates? I suspect that PIMPL works better for this...

> Oh, and you didn't mention that this class namespace can be re-opened
> multiple times or not.

Of course it can. It's just syntax sugar for outscoping a prefix on all
the contained members. There's nothing "exclusive" about that. Just like
you would be able to mix old-style fully prefixed definitions with
definitions in a class name scope.

I added an explanatory note to the proposal text. Thanks again!

--
Matthew

Evan Teran

unread,
Nov 20, 2015, 11:26:33 AM11/20/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com

I just wanted to say that this proposal is looking great. Thanks for taking the time to turn the discussion into something more formal. I am really hopeful that this feature gets taken seriously since I think that it is very useful addition. One thing that may be worth mentioning in the proposal is that similar syntax is already in the language, so this would actually make things more consistent in some ways. Given a header with:

// Foo.h
namespace Foo {
void method();
}


We have the option of defining Foo::method() a few ways:

namespace Foo {
void method() {
   
// ...
}
}


// or


or Foo::method() {
   
// ...
}

The fact that you can't do similar for classes and structs is actually a point of inconsistency.

Bengt Gustafsson

unread,
Nov 20, 2015, 7:49:54 PM11/20/15
to ISO C++ Standard - Future Proposals
I like this idea a lot, but I'm sceptical to the reuse of the word namespace. There is also another proposal that uses the same syntax with a different meaning, which indicates that it may be non-intuitive. I like that proposal too, which is using namespace as another protection level besides private, protected and public; with the obvious meaning. AFAIK the idea was not to require a namespace: on namespace level for declaring top level classes to be visible only inside the namespace, but instead do it "Java style" with namespace class X syntax just like this proposal.

In fact I think that is a more appropriate use of this syntax.

Ideally we would have a very readable syntax like this:

[template<...>] class A namespace {
};

This reads better I think: We're now entering the class A namespace, right? While this opens up for the cumbersome "namespace class A namespace { ... } to define the methods of a class A with namespace visibility it is at least still logical, and the combination will be quite rare.

--------

I also want to comment on the idea of allowing additional methods inside such an implementation clause. I think it is doable, and a good thing, given the right rules: Only methods declared in the "real" class head have access to private members, or maybe even better: Such extra methods must be private so that they can be used only by the "real" methods of the class (directly or indirectly). Their visibility would have to be limited to the SAME implementation clause as we would otherwise run into trouble with what happens with two such clauses in different TUs requiring magic (aka modules) to transfer the information between the clauses.

This said, it would of course not be possible to add virtual methods or non-static data members, i.e. anything that affects the memory layout of the objects (by this rule local class declarations would be allowed).

I know there have been proposals in this direction before, and I think this is the right time to cater for those needs without creating yet another feature.

A possible killer drawback is however that we get into the "override" problem: If we change the signature of a method in the class head the implementation silently turns into a extra method. On the other hand this is only silent until link time when it becomes painfully obvious that there is a mismatch...

Nicol Bolas

unread,
Nov 20, 2015, 9:01:30 PM11/20/15
to ISO C++ Standard - Future Proposals
On Friday, November 20, 2015 at 7:49:54 PM UTC-5, Bengt Gustafsson wrote:
I like this idea a lot, but I'm sceptical to the reuse of the word namespace. There is also another proposal that uses the same syntax with a different meaning, which indicates that it may be non-intuitive. I like that proposal too, which is using namespace as another protection level besides private, protected and public; with the obvious meaning.

As far as I'm concerned, syntax should be apportioned on two bases: merit and first-come-first-serve. The merits of this proposal may be syntactic sugar, but basically nobody liked the "namespace protection level" idea except the person who suggested it.

And for first-come-first-serve, this is actually a proposal. Not yet submitted to the committee, but it's actually got paper behind it. Whereas the "namespace protection level" was nothing more than an idea someone had. And not a particularly well-considered idea either.

So this proposal is both more generally useful and more well-thought out than that idea. It's got dibs on the syntax.
 
I also want to comment on the idea of allowing additional methods inside such an implementation clause. I think it is doable, and a good thing, given the right rules: Only methods declared in the "real" class head have access to private members, or maybe even better: Such extra methods must be private so that they can be used only by the "real" methods of the class (directly or indirectly). Their visibility would have to be limited to the SAME implementation clause as we would otherwise run into trouble with what happens with two such clauses in different TUs requiring magic (aka modules) to transfer the information between the clauses.

Scope creep is bad. This feature is about making syntax better, not about allowing people to inject methods into classes.

What's more, the committee has already made a determination on a similar proposal called "extension methods". And that determination was "no." Indeed, "extension methods" was apparently unwanted even by those who wanted to see automatic deduction of `f(x)` from `x.f()`.

Adding your idea to the proposal would lead either to its failure entirely or to the committee requesting that the offending parts be removed. Either way, it's a waste of time.
 
This said, it would of course not be possible to add virtual methods or non-static data members, i.e. anything that affects the memory layout of the objects (by this rule local class declarations would be allowed).

I know there have been proposals in this direction before, and I think this is the right time to cater for those needs without creating yet another feature.

Piggybacking your pet feature onto someone else's proposal is not a good way to get either one adopted. Especially since the committee has already said no.

Matthew Woehlke

unread,
Nov 23, 2015, 10:29:44 AM11/23/15
to std-pr...@isocpp.org
On 2015-11-20 21:01, Nicol Bolas wrote:
> And for first-come-first-serve, this is actually a proposal. Not yet
> submitted to the committee, but it's actually got paper behind it.

It's also (I literally just discovered) apparently an exact duplicate of
N1420. Which appears to have fizzled (i.e. wasn't actually rejected, but
just fell off the radar for whatever reasons).

That being the case, this will need some revision/updates before I want
to submit it to take that into account. Maybe we can have better luck
this time around. (Or should I just pick up N1420 instead?)

--
Matthew

Matthew Woehlke

unread,
Nov 23, 2015, 10:30:26 AM11/23/15
to std-pr...@isocpp.org
On 2015-11-20 19:49, Bengt Gustafsson wrote:
> I like this idea a lot, but I'm sceptical to the reuse of the word
> namespace. There is also another proposal that uses the same syntax with a
> different meaning, which indicates that it may be non-intuitive.

You are talking about the namespace access protection proposal? Leaving
aside that that got very little support, how did that reuse the syntax?
My understanding was that that added:

class Foo
{
public:
...
private:
...
namespace: // new
...
}

I don't see how that overlaps.

> Ideally we would have a very readable syntax like this:
>
> [template<...>] class A namespace {
> };

That, to me, is backwards. When opening a regular namespace, the syntax
order is <verb¹ (keyword)> <noun (identifier)>. Why would we want to use
the completely different order <adjective> <noun> <verb>?

(¹ I'm calling "namespace" a verb, here, because its the token that
indicates what action is occurring.)

> This reads better I think: We're now entering the class A namespace, right?

I'd buy that argument if we also wrote "std namespace { ... }". But we
don't.

> I also want to comment on the idea of allowing additional methods inside
> such an implementation clause. I think it is doable, and a good thing,
> given the right rules [...]

I am not going to add this to the proposal. My understanding is that
this sort of thing is highly controversial and tanked a previous
proposal. I see no reason why the proposal as is should be risked just
to try to rush a feature that could² as easily be added later.

(² In the technical sense. In the practical sense it seems already that
actually doing so has the proverbial snowball's chance.)

See also Nicol's comments.

> A possible killer drawback is however that we get into the "override"
> problem: If we change the signature of a method in the class head the
> implementation silently turns into a extra method.

Pedantic: that's an over*load*, not an over*ride*.

--
Matthew

Nicol Bolas

unread,
Nov 23, 2015, 11:27:52 AM11/23/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com

You could probably consider yours a revision of N1420. Either way, you should probably give acknowledgements and also try to hunt down what people thought of the proposal, so that you can be ready to answer any questions that might have been raised.

Bengt Gustafsson

unread,
Nov 24, 2015, 5:39:54 PM11/24/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
Maybe I was over-reading the suggestion about a namespace protection level. To me it was obvious that the most common use case would be to protect some of the classes from outside access, as is today commonly done using the detail sub-namespace. So I assumed that this would be possible:

namespace my_namespace {
  namespace class Foo {  // A namespace local helper class.

  public: 
    ... 
  private: 
    ... 
  namespace: // new 
    ... 
  };
}

Anyhow, maybe this purpose would be better served by allowing private: and public: on the namespace level. This of course offers more protection than the current detail:: system but I will not say more about it as it is off topic here.

When it comes to the order of the keywords I would be hard pressed to view namespace as a verb anytime. With class A namespace { you get the important information first, it is a class we're talking about, and then later that we are reopening it. That said, of course I'd rather have it the other way around than not at all.

Andrew Tomazos

unread,
Nov 25, 2015, 2:37:45 AM11/25/15
to std-pr...@isocpp.org
On Sat, Nov 21, 2015 at 3:01 AM, Nicol Bolas <jmck...@gmail.com> wrote:
As far as I'm concerned, syntax should be apportioned on two bases: merit and first-come-first-serve.

Ummm.  Yes, proposals are evaluated based on their merits.  The merits in the opinion of people who show up to meetings and vote, after a presentation and discussion (and some of those present will have actually read the paper carefully from the mailing).

I have no idea what the "first-come-first-serve" part is you are talking about.  If there are competing/conflicting proposals, which one came first has no bearing on how people vote as far as I can tell.  It's not even clear why it would or should.

The merits of this proposal may be syntactic sugar, but basically nobody liked the "namespace protection level" idea except the person who suggested it.
 
You can't tell that from a std-proposals thread.  The general sentiment on std-proposals doesn't really correlate well with how proposals go at meetings.  This list is useful for finding out some specific points of interest about initial proposal ideas through to preliminary drafts - but you certainly shouldn't try to extrapolate how the meeting votes will go based on totaling positive-tone vs negative-tone responses on this list.  I won't speculate why it doesn't work, except to say that it just doesn't.


Matthew Woehlke

unread,
Nov 25, 2015, 9:59:18 AM11/25/15
to std-pr...@isocpp.org
On 2015-11-24 17:39, Bengt Gustafsson wrote:
> Maybe I was over-reading the suggestion about a namespace protection level.
> To me it was obvious that the most common use case would be to protect some
> of the classes from outside access, as is today commonly done using the
> detail sub-namespace. So I assumed that this would be possible:
>
> namespace my_namespace {
> namespace class Foo { // A namespace local helper class.

What do you think the use of "namespace" here means? (It's not currently
allowed; why would namespace access protection allow it, and what would
it mean?)

> public:
> ...
> private:
> ...
> namespace: // new
> ...
> };
> }
>
> Anyhow, maybe this purpose would be better served by allowing private: and
> public: on the namespace level. This of course offers more protection than
> the current detail:: system but I will not say more about it as it is off
> topic here.

I'm not aware of any proposal like this, even for namespace as the
access level. (What, for example, would private mean, anyway? Private to
what?)

I'm also not convinced it's necessary; if no class members have access
beyond namespace, you get pretty much the same effect.

> When it comes to the order of the keywords I would be hard pressed to view
> namespace as a verb anytime.

What do you consider it in the case e.g. "namespace std"? I read that as
"namespace" -> verb, I am opening a namespace, "std" -> noun, the
namespace I am opening. Just like "class" in a class definition is a
verb ("I am defining a class").

> With class A namespace { you get the important
> information first, it is a class we're talking about, and then later that
> we are reopening it. That said, of course I'd rather have it the other way
> around than not at all.

Again, why then do we write "namespace std" instead of "std namespace"?

I too would rather have "class <name> namespace" than nothing :-), but
that order feels unnatural to me.

--
Matthew

Nicol Bolas

unread,
Nov 25, 2015, 10:05:46 AM11/25/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
On Wednesday, November 25, 2015 at 9:59:18 AM UTC-5, Matthew Woehlke wrote:
On 2015-11-24 17:39, Bengt Gustafsson wrote:
> Maybe I was over-reading the suggestion about a namespace protection level.
> To me it was obvious that the most common use case would be to protect some
> of the classes from outside access, as is today commonly done using the
> detail sub-namespace. So I assumed that this would be possible:
>
> namespace my_namespace {
>   namespace class Foo {  // A namespace local helper class.

What do you think the use of "namespace" here means? (It's not currently
allowed; why would namespace access protection allow it, and what would
it mean?)

>   public:
>     ...
>   private:
>     ...
>   namespace: // new
>     ...
>   };
> }
>
> Anyhow, maybe this purpose would be better served by allowing private: and
> public: on the namespace level. This of course offers more protection than
> the current detail:: system but I will not say more about it as it is off
> topic here.

I'm not aware of any proposal like this, even for namespace as the
access level. (What, for example, would private mean, anyway? Private to
what?)

Just FYI: what he's referring to is an idea that was batted around here a few weeks ago.

Nicol Bolas

unread,
Nov 25, 2015, 10:10:40 AM11/25/15
to ISO C++ Standard - Future Proposals
On Wednesday, November 25, 2015 at 2:37:45 AM UTC-5, Andrew Tomazos wrote:
On Sat, Nov 21, 2015 at 3:01 AM, Nicol Bolas <jmck...@gmail.com> wrote:
As far as I'm concerned, syntax should be apportioned on two bases: merit and first-come-first-serve.

Ummm.  Yes, proposals are evaluated based on their merits.  The merits in the opinion of people who show up to meetings and vote, after a presentation and discussion (and some of those present will have actually read the paper carefully from the mailing).

I have no idea what the "first-come-first-serve" part is you are talking about.  If there are competing/conflicting proposals, which one came first has no bearing on how people vote as far as I can tell.  It's not even clear why it would or should.

But that's usually because people avoid conflicting syntax in the first place. If there's a proposal that uses some syntax that has general committee approval and standard wording, and you're starting a proposal that would rather use that syntax for something else, odds are really good that among the suggestions for improving it will be "Proposal X has dibs on that syntax; find something else."

For example, right now I would not suggest making a proposal that uses `auto {...}` syntax in a way that conflicts with P0144.
 
The merits of this proposal may be syntactic sugar, but basically nobody liked the "namespace protection level" idea except the person who suggested it.
 
You can't tell that from a std-proposals thread.  The general sentiment on std-proposals doesn't really correlate well with how proposals go at meetings.

In some ways, this is true. The committee has shot down plenty of proposals that had broad approval on this forum. And the committee has accepted many proposals that haven't exactly achieved consensus here. However, I don't recall a time when a proposal suggested here gained basically universal disapproval, yet fared well in the committee.

So I'd say that, while approval here doesn't mean that it will pass muster, widespread dislike here probably is a bad sign. Especially when that widespread dislike includes the EWG chair saying this:

A new access mode needs very strong motivation; it's not sufficient that it doesn't cause damage, or that it would be nice for a few selected examples. It must be of fundamental importance. Is it?

This is hardly a guarantee of failure, but I wouldn't be too hopeful just the same. Not until you can find a really good answer to that question.

Matthew Woehlke

unread,
Nov 25, 2015, 10:37:51 AM11/25/15
to std-pr...@isocpp.org
On 2015-11-25 09:58, Matthew Woehlke wrote:
> On 2015-11-24 17:39, Bengt Gustafsson wrote:
>> Anyhow, maybe this purpose would be better served by allowing private: and
>> public: on the namespace level. This of course offers more protection than
>> the current detail:: system but I will not say more about it as it is off
>> topic here.
>
> I'm not aware of any proposal like this, even for namespace as the
> access level. (What, for example, would private mean, anyway? Private to
> what?)

Oh, sorry, I misread what you wrote. Now I understand what you are
saying. Off topic, but potentially interesting.

--
Matthew

Andrew Tomazos

unread,
Nov 25, 2015, 1:22:30 PM11/25/15
to std-pr...@isocpp.org
On Wed, Nov 25, 2015 at 4:10 PM, Nicol Bolas <jmck...@gmail.com> wrote:
On Wednesday, November 25, 2015 at 2:37:45 AM UTC-5, Andrew Tomazos wrote:
On Sat, Nov 21, 2015 at 3:01 AM, Nicol Bolas <jmck...@gmail.com> wrote:
As far as I'm concerned, syntax should be apportioned on two bases: merit and first-come-first-serve.

Ummm.  Yes, proposals are evaluated based on their merits.  The merits in the opinion of people who show up to meetings and vote, after a presentation and discussion (and some of those present will have actually read the paper carefully from the mailing).

I have no idea what the "first-come-first-serve" part is you are talking about.  If there are competing/conflicting proposals, which one came first has no bearing on how people vote as far as I can tell.  It's not even clear why it would or should.

But that's usually because people avoid conflicting syntax in the first place. If there's a proposal that uses some syntax that has general committee approval and standard wording, and you're starting a proposal that would rather use that syntax for something else, odds are really good that among the suggestions for improving it will be "Proposal X has dibs on that syntax; find something else."

For example, right now I would not suggest making a proposal that uses `auto {...}` syntax in a way that conflicts with P0144.

If you have a better idea for something that auto {...} should mean, by all means propose it.

As it happens there are other ideas floating around for what auto { ... } could mean.  It could mean a temporary of deduced type from a braced-init-list, for example maybe a std::initializer_list.  This possibility (at least syntactically) is one of the problems with the proposal as I point out in P0151.

Don't be intimidated because Herb/Bjarne/Gaby's names are on the paper.  Papers are not evaluated based on who wrote them.  Author reputation has only a very weak influence.  We hope proposals are objectively evaluated based on their content (time permitting).
 
So I'd say that, while approval here doesn't mean that it will pass muster, widespread dislike here probably is a bad sign. Especially when that widespread dislike includes the EWG chair saying this:

A new access mode needs very strong motivation; it's not sufficient that it doesn't cause damage, or that it would be nice for a few selected examples. It must be of fundamental importance. Is it?

This is hardly a guarantee of failure, but I wouldn't be too hopeful just the same. Not until you can find a really good answer to that question.

Ville is just pointing out that a new access mode needs very strong motivation (that's exactly what he said in fact).  He made that comment in response to someone else that was defending the idea w.r.t the "openness" issue.  The "openness" issue was getting far too much air-time.

The two points I take away from the responses are:

- A namespace access level would need to be contrasted with the proposed "internal" access level of modules.  We would need to show such an access level will still be relevant in a modules-world.  As it looks like modules and namespaces are going to be distinct and orthogonal, I think this can be done.

- We would need to explore the "openness" of namespaces and how it relates to the access level.  Although I think modules are open too, so this is the same issue for internal module access.  I think the importance of the issue was exadurated on std-proposals.

Beyond those two points there was very little else said.  Predicting how EWG will react to a proposal is extremely difficult - and while I appreciate your attempt to do so for mine - I think it may be beyond your abilities. :)

Matthew Woehlke

unread,
Nov 25, 2015, 2:30:31 PM11/25/15
to std-pr...@isocpp.org
On 2015-11-19 14:42, Matthew Woehlke wrote:
> I've written up a draft proposal for a "class namespace" feature based
> on the recent thread. In short, it introduces the new syntax:
>
> template <...> // optional
> namespace class Foo
> {
> Foo(...) { ... }
> void foo(...) { ... }
> }
>
> ...which is equivalent to:
>
> template <...> Foo<...>::Foo(...) { ... }
> template <...> void Foo<...>::foo(...) { ... }
>
> Basically, it allows one to "hoist" the class name (along with template
> specifications) out of a collection of out-of-line class member
> definitions and into a block scope. The class name (and template bits)
> are then implicitly applied to all definitions within said scope.
>
> I'm attaching the current version for you lazy people that like to see
> it in-line :-). You can also find the up to date version (with pretty
> HTML formatting) at
> https://github.com/mwoehlke/cpp-proposals/blob/Pxxx-class-namespace/PXXXX%20Class%20Namespace.rst.

Updated version, for lazy folks, attached. I've added reference to N1420
and made "natural consequences" more explicit.

Still TO-DO: try to get in touch with Carl Daniel (N1420) and Vincent
Ordy (who apparently was implementing this in some fashion).

--
Matthew
PXXXX Class Namespace.rst

Bengt Gustafsson

unread,
Nov 25, 2015, 6:02:56 PM11/25/15
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
Reading through today's posts I think that the confusion has been reduced. There are three suggestions around:

1) The topic of this thread: Reopening a class for implementation purposes. Using namespace at either end of the introducer is fine with me. I think the quite dramatic clutter reduction in the later half of include files makes it worth the while.

2) The previous suggestion regarding a namespace: possibility inside classes to restrict use of specific members to the surrounding namespace. This is what didn't get very much traction, but if anyone wants to formalize it that's fine with me.

3) My suggestion of allowing private: (and hence public:) on namespace level to serve the purpose of the current rather clumsy "detail" namespace. This has two benefits: a) it makes it harder to break in to private parts of the namespace, b) it makes namespaces and classes more similar, one less difference to teach. I see some merit to this, but I don't think it is worth focussing standardization work on. If someone wants to do it, fine, ubt I'm not going to push it further.

Péter Radics

unread,
Nov 26, 2015, 4:20:49 AM11/26/15
to std-pr...@isocpp.org
I found this paper describing the implementation.  Apparently it's done via some code transformation tool: https://www.lrde.epita.fr/dload/20080709-Seminar/ordy-classnamespaces.pdf


Péter

unread,
Dec 1, 2015, 8:38:59 AM12/1/15
to ISO C++ Standard - Future Proposals
Since unions can have member functions too, wouldn't it be better to extend this facility to unions as well?  Of course union should not be interchangeable with struct/class: "namespace union Foo" must refer to a previously declared "union Foo", not a class or struct Foo.

Paul

unread,
Mar 22, 2016, 3:47:48 PM3/22/16
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
Has there been any updates on this proposal (Maybe in Jacksonville?) ?.

Matthew Woehlke

unread,
Mar 22, 2016, 4:08:00 PM3/22/16
to std-pr...@isocpp.org
On 2016-03-22 15:47, Paul wrote:
> Has there been any updates on this proposal (Maybe in Jacksonville?) ?.

It wasn't presented. A few individuals expressed that they thought it
doesn't go far enough, i.e. that 'using <classname>' should also be
supported. Others waved their arms making noises of doom and gloom
regarding name lookup.

The general impression I got was that it needs an implementation to be
seriously considered. (At any rate, it won't be in C++17.)

--
Matthew

Paul

unread,
Mar 22, 2016, 4:46:21 PM3/22/16
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
That's really disappointing.
I have just started again using C++ and of course there were tons of class templates everywhere with these awful long instantiation names.


On Tuesday, March 22, 2016 at 9:08:00 PM UTC+1, Matthew Woehlke wrote:
On 2016-03-22 15:47, Paul wrote:
> Has there been any updates on this proposal (Maybe in Jacksonville?) ?.

It wasn't presented. A few individuals expressed that they thought it
doesn't go far enough, i.e. that 'using <classname>' should also be
supported. Others waved their arms making noises of doom and gloom
regarding name lookup.

Could you explain more about these "issues" in name lookup?.

Matthew Woehlke

unread,
Mar 22, 2016, 5:10:18 PM3/22/16
to std-pr...@isocpp.org
On 2016-03-22 16:46, Paul wrote:
> On Tuesday, March 22, 2016 at 9:08:00 PM UTC+1, Matthew Woehlke wrote:
>> On 2016-03-22 15:47, Paul wrote:
>>> Has there been any updates on this proposal (Maybe in Jacksonville?) ?.
>>
>> It wasn't presented.
>
> That's really disappointing. I have just started again using C++ and
> of course there were tons of class templates everywhere with these
> awful long instantiation names.

Do you have examples you can share? Anything that can add to the
motivation would help...

>> A few individuals expressed that they thought it doesn't go far
>> enough, i.e. that 'using <classname>' should also be supported.
>> Others waved their arms making noises of doom and gloom regarding
>> name lookup.
>
> Could you explain more about these "issues" in name lookup?.

No. At least one of the compiler devs had strong words about how 'lookup
is the scariest part of the compiler and I'm opposed in principle to
anything going in there and mucking about'. No details were given, just
general statements made. (Personally, I think concerns here are not
rational - compilers already know how to do name lookup in the context
that P0223 would create - but as mentioned, the impression I was given
was that there would be a lot of opposition without an implementation to
prove that such concerns are unfounded.)

--
Matthew

Paul

unread,
Mar 22, 2016, 5:36:09 PM3/22/16
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
On Tuesday, March 22, 2016 at 10:10:18 PM UTC+1, Matthew Woehlke wrote:
On 2016-03-22 16:46, Paul wrote:
> On Tuesday, March 22, 2016 at 9:08:00 PM UTC+1, Matthew Woehlke wrote:
>> On 2016-03-22 15:47, Paul wrote:
>>> Has there been any updates on this proposal (Maybe in Jacksonville?) ?.
>>
>> It wasn't presented.
>
> That's really disappointing. I have just started again using C++ and
> of course there were tons of class templates everywhere with these
> awful long instantiation names.

Do you have examples you can share? Anything that can add to the
motivation would help...


I think your proposal already contains such examples. My code looks like this:

  template <typename Wrapper, typename SBType, typename... DefaultTypes>
  class SBWrapper : public Nan::ObjectWrap {
  private:
    using ThisTy = SBWrapper<Wrapper, SBType, DefaultTypes...>;

  public:
   ...
  }
  
  template <typename Wrapper, typename SBType, typename... DefaultTypes>
  Nan::Persistent<v8::FunctionTemplate>
      SBWrapper<Wrapper, SBType, DefaultTypes...>::s_ConstTemplate;

  template <typename Wrapper, typename SBType, typename... DefaultTypes>
  Nan::Persistent<v8::Function>
      SBWrapper<Wrapper, SBType, DefaultTypes...>::s_Constructor;

  template <typename Wrapper, typename SBType, typename... DefaultTypes>
  SBWrapper<Wrapper, SBType, DefaultTypes...>::SBWrapper(
      const SBType& SbObject) : m_SBObject{SbObject} {
  }

  template <typename Wrapper, typename SBType, typename... DefaultTypes>
  void SBWrapper<Wrapper, SBType, DefaultTypes...>::Initialize(
      const v8::Local<v8::Object>& exports) {
  }

And I think I am going to add even more template parameters and as you can clearly see, lots of redundant typing (C&P), unclear/confusing code, ...
One could argue that I should simply move all the code into the class scope but I prefer keeping "interface and implementation" separate just for the sake of more code clarity :).
 
With you proposal my code could look like this:

template <typename Wrapper, typename SBType, typename... DefaultTypes>
namespace class SBWrapper {
  Nan::Persistent<v8::FunctionTemplate> s_ConstTemplate;
  Nan::Persistent<v8::Function> s_Constructor;

  SBWrapper(const SBType& SbObject) : m_SBObject{SbObject} {
  }

  void Initialize(const v8::Local<v8::Object>& exports) {
  }
}

:)

Nicol Bolas

unread,
Mar 22, 2016, 11:34:20 PM3/22/16
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com

I'm curious. When Bjarne Stroustrup and Herb Sutter were playing around with unified function call syntax, did anyone ever ask them if someone had implemented their incredibly complicated name lookup rules?

It's not like your proposal was anywhere nearly as complex look-up wise. Especially considering that yours doesn't actually affect name lookup...

Jim Porter

unread,
Mar 23, 2016, 12:00:27 AM3/23/16
to std-pr...@isocpp.org
On 3/22/2016 4:36 PM, Paul wrote:
> One could argue that I should simply move all the code into the class
> scope but I prefer keeping "interface and implementation" separate just
> for the sake of more code clarity :).

Well, it's somewhat beside the point, but unless you have no private
members, you have to mix interface and implementation anyway. :)

- Jim


Reza Jahanbakhshi

unread,
Mar 23, 2016, 12:06:00 AM3/23/16
to std-pr...@isocpp.org
I prefer keeping "interface and implementation" separate just for the sake of more code clarity 
 
Me too. I always separate the implementations in a .inl or .icc header to keep the interface clean. But the implementation header gets really ugly and unreadable exactly because of the problem which this proposal is going to solve. That's why I'm interested it this proposal too. It's really disappointing to see it's not going anywhere soon.




--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/nct4ch%24emp%241%40ger.gmane.org.

Reply all
Reply to author
Forward
0 new messages