Group Member Specifiers

295 views
Skip to first unread message

Andrew Tomazos

unread,
Dec 19, 2013, 6:50:32 AM12/19/13
to std-pr...@isocpp.org
Let us define the Member Specifiers collectively as the non-type-specifer decl-specifiers, the access-specifiers, virt-specifiers and pure specifier as well as the two function bodies =delete and =default - and remove from that set those that can never apply to a member declaration.

Specifically the Member Specifiers are

    member-specifier:
        friend
        typedef
        constexpr
        static
        thread_local
        mutable
        inline
        virtual
        explicit
        override
        final
        = 0
        = delete
        = default
        public
        private
        protected

Let us then define a comma-separated unordered subset of these:

    member-specifier-list:
        member-specifier
        member-specifier-list , member-specifier

Now consider the C++ grammar with access-specifier replaced with member-specifier-list:

    member-specification:
        member-declaration member-specification_opt
        member-specifier-list : member-specification_opt

The semantics are that each member-specifier in the member-specifier-list is applied to each of the following member-declarations up until the next member-specifier-list, exactly as if each member declaration had been explicitly declared with that member-specifier.

Many times we want to specify a sequence of related member declarations with one or more common member-specifier.  Rather than repeat the specifier in each member declaration of the group, a member-specifier-list allows us to specify the member-specifiers once at the start of the group.   This can in some cases lead to a much cleaner and easier to read and maintain class specifier, as it removes noisy repetition.

Open questions/thoughts:
- Should member-specifier-list be comma-separated or space-separated
- Should the access-specifiers orthogonally be allowed as decl-specifiers (like in Java/C#).
- Is there a better way to terminate the group than up until the next member-specifier-list
- Should items be added, renamed or removed from member-specifier
- Should we add something similar at namespace-scope for namespace members.

Feedback welcome and appreciated.

Ville Voutilainen

unread,
Dec 19, 2013, 8:29:17 AM12/19/13
to std-pr...@isocpp.org
On 19 December 2013 13:50, Andrew Tomazos <andrew...@gmail.com> wrote:
> Let us define the Member Specifiers collectively as the non-type-specifer
> decl-specifiers, the access-specifiers, virt-specifiers and pure specifier
> as well as the two function bodies =delete and =default - and remove from
> that set those that can never apply to a member declaration.
> Let us then define a comma-separated unordered subset of these:
>
> member-specifier-list:
> member-specifier
> member-specifier-list , member-specifier
>
> Now consider the C++ grammar with access-specifier replaced with
> member-specifier-list:


Did you plan to show an example of what you're striving for here and
why? I don't
speak grammar. :) In other words, examples and motivation, please.

DeadMG

unread,
Dec 19, 2013, 9:00:39 AM12/19/13
to std-pr...@isocpp.org
A basic example is access specifiers. Consider public. In C++, you have

class X {
public:
    /* All the things I want public */
private:
    /* All the other things */
};

In Java or C#, you must affix every member with public, like

class X {
    public void f();
    public void g();
};

But in C++, they use a Java-style approach for virtual- you have to define every individual function as virtual. He wants to be able to set blocks of functions as virtual, the way you can now for access specifiers.

Andrew Tomazos

unread,
Dec 19, 2013, 9:03:15 AM12/19/13
to std-pr...@isocpp.org
Sure, it's actually pretty simple:

Sure, it's actually pretty simple.  So instead of:

class IXMLProcessor
{
public:
    virtual void startDocument() = 0;
    virtual void endDocument() = 0;
    
    virtual void startElement(const QName *name) = 0;
    virtual void endElement() = 0;
    virtual void attribute(const QName *name, const String &text) = 0;
    
    virtual void text(const String &text) = 0;
    virtual void comment(const String &text) = 0;

virtual ~XMLStream() {}
};

class MyXMLProcessor
{
public:
    virtual void startDocument() override;
    virtual void endDocument() override;
    
    virtual void startElement(const QName *name) override;
    virtual void endElement() override;
    virtual void attribute(const QName *name, const String &text) override;
    
    virtual void text(const String &text) override;
    virtual void comment(const String &text) override;

virtual ~XMLStream() {}
};

You could write:

class IXMLProcessor
{
public, virtual, =0:
    void startDocument();
    void endDocument();
    
    void startElement(const QName *name);
    void endElement();
    void attribute(const QName *name, const String &text);
    
    void text(const String &text);
    void comment(const String &text);

public:
virtual ~XMLStream() {}
};

class MyXMLProcessor
{
public, virtual, override:
    void startDocument();
    void endDocument();
    
    void startElement(const QName *name);
    void endElement();
    void attribute(const QName *name, const String &text);
    
    void text(const String &text);
    void comment(const String &text);
};

And instead of:

template<class T>
class numeric_limits
{
  public:
    static constexpr const  bool  is_specialized    = false;
    static constexpr        T     min()             __ntl_nothrow;
    static constexpr        T     max()             __ntl_nothrow;
    static constexpr        T     lowest()          __ntl_nothrow;
    static constexpr const  int   digits            = 0;
    static constexpr const  int   digits10          = 0;
    static constexpr const  bool  is_signed         = false;
    static constexpr const  bool  is_integer        = false;
    static constexpr const  bool  is_exact          = false;
    static constexpr const  int   radix             = 0;
    static constexpr        T     epsilon()         __ntl_nothrow;
    static constexpr        T     round_error()     __ntl_nothrow;
    static constexpr const  int   min_exponent      = 0;
    static constexpr const  int   min_exponent10    = 0;
    static constexpr const  int   max_exponent      = 0;
    static constexpr const  int   max_exponent10    = 0;
    static constexpr const  bool  has_infinity      = false;
    static constexpr const  bool  has_quiet_NaN     = false;
    static constexpr const  bool  has_signaling_NaN = false;
    static constexpr const  float_denorm_style  has_denorm  = denorm_absent;
    static constexpr const  bool  has_denorm_loss   = false;
    static constexpr        T     infinity()        __ntl_nothrow;
    static constexpr        T     quiet_NaN()       __ntl_nothrow;
    static constexpr        T     signaling_NaN()   __ntl_nothrow;
    static constexpr        T     denorm_min()      __ntl_nothrow;
    static constexpr const  bool  is_iec559         = false;
    static constexpr const  bool  is_bounded        = false;
    static constexpr const  bool  is_modulo         = false;
    static constexpr const  bool  traps             = false;
    static constexpr const  bool  tinyness_before   = false;
    static constexpr const  float_round_style round_style = round_toward_zero;
}; //template class numeric_limits

You could write:

template<class T>
class numeric_limits
{
  public, static, constexpr:
    const  bool  is_specialized    = false;
           T     min()             __ntl_nothrow;// { return T(false); }
           T     max()             __ntl_nothrow;// { return T(false); }
           T     lowest()          __ntl_nothrow;// { return T(false); }
    const  int   digits            = 0;
    const  int   digits10          = 0;
    const  bool  is_signed         = false;
    const  bool  is_integer        = false;
    const  bool  is_exact          = false;
    const  int   radix             = 0;
           T     epsilon()         __ntl_nothrow;// { return T(false); }
           T     round_error()     __ntl_nothrow;// { return T(false); }
    const  int   min_exponent      = 0;
    const  int   min_exponent10    = 0;
    const  int   max_exponent      = 0;
    const  int   max_exponent10    = 0;
    const  bool  has_infinity      = false;
    const  bool  has_quiet_NaN     = false;
    const  bool  has_signaling_NaN = false;
    const  float_denorm_style  has_denorm  = denorm_absent;
    const  bool  has_denorm_loss   = false;
           T     infinity()        __ntl_nothrow;// { return T(false); }
           T     quiet_NaN()       __ntl_nothrow;// { return T(false); }
           T     signaling_NaN()   __ntl_nothrow;// { return T(false); }
           T     denorm_min()      __ntl_nothrow;// { return T(false); }
    const  bool  is_iec559         = false;
    const  bool  is_bounded        = false;
    const  bool  is_modulo         = false;
    const  bool  traps             = false;
    const  bool  tinyness_before   = false;
    const  float_round_style round_style = round_toward_zero;
};

Ville Voutilainen

unread,
Dec 19, 2013, 9:09:41 AM12/19/13
to std-pr...@isocpp.org
On 19 December 2013 16:03, Andrew Tomazos <andrew...@gmail.com> wrote:
> Sure, it's actually pretty simple. So instead of:


Thanks for the example. I'm cautiously for this idea, but I'm not sure
the examples
are practically convincing. And I expect to hear that argument in a
stronger fashion
from other people.

We actually very briefly discussed making override/final member
specifiers, but that
idea didn't get anywhere. It was practically ignored, although I don't know why.

Andrew Tomazos

unread,
Dec 19, 2013, 9:39:18 AM12/19/13
to std-pr...@isocpp.org
override and final are context-sensitive keywords, so it would be a hassle for the parser to deal with them in a decl-specifier-seq.  That is my understanding of why they are in the suffix of a function declarator.  That is just syntactic however and semantically they are essentially specifiers that modify a member function declaration, so I include them in the initial proposed list of possible member-specifiers.  I think parsing a member-specifier-list is pretty easy, but need to study it further.  In the worst case we could have a member-specifier-list introduced by an initial access-specifier - but those are pretty minor details at this stage.

Also of interest from an existing practice pov is Qt signals and slots which use this same type of group specifier syntax to define a group of members that are all signals or all slots.

Maurice Bos

unread,
Dec 19, 2013, 10:20:29 AM12/19/13
to std-pr...@isocpp.org
This sounds a lot like how attributes can be used in D: http://dlang.org/attribute.html

The behaviour in D is a little bit different than proposed. After "override:", everything till the end of the class is override. A "public:" or something later would not turn 'override' off. Apart from "attribute:", there is also "attribute { ... }", which gives better control over to what the attribute is applied.

Being able to do something like

static constexpr {
     public:
          ...
     private:
          ...
}

or

public:
   static {
      ...
   }
   ...

(in addition to what's originally proposed), would make it even more useful.

-Maurice-


2013/12/19 Andrew Tomazos <andrew...@gmail.com>

--
 
---
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/.

Thiago Macieira

unread,
Dec 19, 2013, 11:59:57 AM12/19/13
to std-pr...@isocpp.org
On quinta-feira, 19 de dezembro de 2013 06:39:18, Andrew Tomazos wrote:
> Also of interest from an existing practice pov is Qt signals and slots
> which use this same type of group specifier syntax to define a group of
> members that are all signals or all slots.

Note that both syntaxes are possible:

class Foo : public QObject
{
Q_OBJECT

public slots: // note absence of comma as precedent
void slot1();

public:
Q_SLOT void slot2();
};

There's also a difference between singular and plural.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
signature.asc

Magnus Fromreide

unread,
Dec 19, 2013, 1:03:12 PM12/19/13
to std-pr...@isocpp.org
On Thu, Dec 19, 2013 at 03:50:32AM -0800, Andrew Tomazos wrote:
> Let us define the Member Specifiers collectively as the non-type-specifer
> decl-specifiers, the access-specifiers, virt-specifiers and pure specifier
> as well as the two function bodies =delete and =default - and remove from
> that set those that can never apply to a member declaration.

Should this allow member attributes, like [[noreturn]], to be specified as
well?

/MF

gmis...@gmail.com

unread,
Dec 19, 2013, 5:49:27 PM12/19/13
to std-pr...@isocpp.org
Maybe it's time to get rid of = 0, and add abstract as a keyword. i.e.:

// Example 1:
class B {
  void f() abstract; // use abstract to mean  = 0;
};

class D : public B {
  void f() override;
};

// Example 2:

class B abstract {
  void f(); // abstract from class declaration.
};

class D : public B {
void f() override;
};

// Example 3:

class B {
abstract:
void f(); // abstract from label declaration:
};

class D : public B {
override:
void f();
};

Klaim - Joël Lamotte

unread,
Dec 19, 2013, 6:13:08 PM12/19/13
to std-pr...@isocpp.org
On Thu, Dec 19, 2013 at 11:49 PM, <gmis...@gmail.com> wrote:
Maybe it's time to get rid of = 0, and add abstract as a keyword. 

Both modifications would, if I understand correctly, not even be considered by the committee if there is not strong rationals providing
example of important problems it would solve. Basically, I don't see how such change would be considered.




The grouping proposal is interesting, I would have to check what kind of impact it could have on my current code bases. 

Ville Voutilainen

unread,
Dec 19, 2013, 6:59:47 PM12/19/13
to std-pr...@isocpp.org
On 20 December 2013 01:13, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> On Thu, Dec 19, 2013 at 11:49 PM, <gmis...@gmail.com> wrote:
>> Maybe it's time to get rid of = 0, and add abstract as a keyword.
> Both modifications would, if I understand correctly, not even be considered
> by the committee if there is not strong rationals providing
> example of important problems it would solve. Basically, I don't see how
> such change would be considered.

We're not going to "get rid of =0". Discussing that is a waste of time.
Regarding abstract as a context-sensitive keyword, I think it should be
very easy to implement and has a certain consistency with override/final.
It would also be very easy to have an abstract function declaration that
is also a definition (although I don't know/remember why we don't support
void foo() = 0 {}). I wouldn't mind having such an abstract keyword,
but I can't really imagine a strong motivation for it that would likely
sway people to support it.

gmis...@gmail.com

unread,
Dec 19, 2013, 8:55:25 PM12/19/13
to std-pr...@isocpp.org
Sorry I didn't mean "get rid of = 0" to suggest actually make it illegal or deprecate it, it was just a bad turn of phrase.

I just meant introduce abstract since it is nicer IMHO. I like abstract as a proposal on it's own, but I suggested abstract as much as an aid to this proposal.

With the kind of fix it tools we are now seeing appear in clang etc. it wouldn't be that hard I would think to create a conversion tool to replace all = 0 with abstract either.

Another related syntactic change but going in the opposite direction might be to allow public: etc. without a colon, for those who prefer to go to be verbose and spell out each function in full. .e.g.:

class B {
  public void f1();
  private void f2();
};

It might be interesting to discuss the merits of verbose and non verbose with regard to cut and pasting lines and how such syntactic option helps or hinders that.


While I'm talking about ideas that probably won't get overwhelming approval regarding these keywords, perhaps it's time to deprecate private inheritance too, such that:

class X : D

generates a warning for the next 10 years, unless : private D is used instead. Then eventually it could be deprecated and default to public inheritance or left as is then as it still improves clarity even if the default is not changed later.

David Krauss

unread,
Dec 19, 2013, 9:11:01 PM12/19/13
to std-pr...@isocpp.org
On 12/20/13 6:49 AM, gmis...@gmail.com wrote:
> Maybe it's time to get rid of = 0, and add abstract as a keyword. i.e.:

A few weeks ago I suggested to allow "! final" (or "not final") as a
synonym for "= 0", and also "! override" to assert that a new interface
is being introduced and avoid collision with a mix-in. The reception
wasn't so great.

Ville Voutilainen

unread,
Dec 20, 2013, 2:51:32 AM12/20/13
to std-pr...@isocpp.org
On 20 December 2013 03:55, <gmis...@gmail.com> wrote:
> Another related syntactic change but going in the opposite direction might
> be to allow public: etc. without a colon, for those who prefer to go to be
> verbose and spell out each function in full. .e.g.:
>
> class B {
> public void f1();
> private void f2();
> };

I fail to see why we'd do this, since it's a difference of one character.

> While I'm talking about ideas that probably won't get overwhelming approval
> regarding these keywords, perhaps it's time to deprecate private inheritance
> too, such that:
> class X : D
> generates a warning for the next 10 years, unless : private D is used

Perhaps not, because I again fail to find sufficient motivation.

masse....@gmail.com

unread,
Dec 20, 2013, 7:42:22 AM12/20/13
to std-pr...@isocpp.org, gmis...@gmail.com


On Friday, December 20, 2013 2:55:25 AM UTC+1, gmis...@gmail.com wrote:
Sorry I didn't mean "get rid of = 0" to suggest actually make it illegal or deprecate it, it was just a bad turn of phrase.

I just meant introduce abstract since it is nicer IMHO. I like abstract as a proposal on it's own, but I suggested abstract as much as an aid to this proposal.

With the kind of fix it tools we are now seeing appear in clang etc. it wouldn't be that hard I would think to create a conversion tool to replace all = 0 with abstract either.

Deprecating the use of " = 0 " in favor of an "abstract" keyword could be a nice addition I think.
The motivation can be that it is more natural for a programmer to use a keyword to mark methods as abstract than the " = 0" trick.
 

Another related syntactic change but going in the opposite direction might be to allow public: etc. without a colon, for those who prefer to go to be verbose and spell out each function in full. .e.g.:

class B {
  public void f1();
  private void f2();
};

It might be interesting to discuss the merits of verbose and non verbose with regard to cut and pasting lines and how such syntactic option helps or hinders that.

I tend to agree, but what about this:

class A {
public :
int method1();
int method2();
private int method3();
int method4();
private static:
void doSomething();
public doSomethingElse();
}

Is method3() public? private?  ill-formed?
same question about method4.
Also, is doSomethingElse static?


While I'm talking about ideas that probably won't get overwhelming approval regarding these keywords, perhaps it's time to deprecate private inheritance too, such that:

class X : D

generates a warning for the next 10 years, unless : private D is used instead. Then eventually it could be deprecated and default to public inheritance or left as is then as it still improves clarity even if the default is not changed later.

I don't really see the improvments here.
 

Andrew Tomazos

unread,
Dec 20, 2013, 9:24:48 AM12/20/13
to std-pr...@isocpp.org, gmis...@gmail.com, masse....@gmail.com
On Friday, December 20, 2013 1:42:22 PM UTC+1, masse....@gmail.com wrote:
I tend to agree, but what about this:

class A {
public :
int method1();
int method2();
private int method3();
int method4();
private static:
void doSomething();
public doSomethingElse();
}

Is method3() public? private?  ill-formed?
same question about method4.
Also, is doSomethingElse static?

(I will assume you meant to type "public void doSomethingElse()" and not "public doSomethingElse()")

In my original proposal the access-specifiers are not allowed as decl-specifiers as is the case now, so under it both method3 and doSomethingElse are ill-formed syntax error.

However suppose we orthogonally added the access-specifiers as decl-specifiers in addition to the proposal.

Then method3 is ill-formed as it is declared both public and private.  It would be like a declaration:

    public private int method3();

doSomethingElse is also ill-formed as it is declared both private and public. It would be like declaring:

    private public static void doSomethingElse();

The implicit member-specifier-list at the start of a class is "private:" and at the start of a struct is "public:".

In this world we would also need a way to declare an empty member-specifier-list.

I'm currently thinking that adding the access-specifiers as decl-specifiers is a bad idea.

An added benefit to not doing so, would free the access-specifier to always introduce a member-specifier-list.  This makes parsing a lot easier and more efficient too, and allows us to definitely use space-separation.

So I amend the proposal as follows:

Remove access-specifier from member-specifier:

    member-specifier:
        friend
        typedef
        constexpr
        static
        thread_local
        mutable
        inline
        virtual
        explicit
        override
        final
        = 0
        = delete
        = default

Define a space-separated unordered subset of these:

    member-specifier-seq:
        member-specifier
        member-specifier-seq member-specifier

Now consider the C++ grammar with access-specifier having an optional member-specifier-seq suffix (instead of being replaced):

    member-specification:
        member-declaration member-specification_opt
        access-specifier member-specifier-seq_opt : member-specification_opt
                         ^^^^^^^^^^^^^^^^^^^^^^^^

Now with a lookahead of one token the parser can determine which of the two member-specification bodies it is in (as it can now).  If it consumes an access-specifier then it consumes member specifiers up until the next colon.

Semantically the member specifiers are then applied to each following declaration up until the next access-specifier or end of the class.

From the users point of view it means that you simply have to place your member specifiers (if any) after an access specifier.  I think this is the best way.

     class C
     {
     public static constexpr: // OK
         /* ... */

     static public constexpr: // ERROR: public must go first
        /* ... */

        public void f(); // ERROR: public is not a decl-specifier (as is the case now)
     };

Ville Voutilainen

unread,
Dec 20, 2013, 10:48:55 AM12/20/13
to std-pr...@isocpp.org
On 20 December 2013 14:42, <masse....@gmail.com> wrote:
> Deprecating the use of " = 0 " in favor of an "abstract" keyword could be a
> nice addition I think.

No thanks. The use of ' = 0' is not broken in any way, so there's no need
to deprecate it. I don't ever want to see an implementation diagnostic
suggesting that all my =0 uses are using a deprecated facility, and if I
do, I'll send angry letters to vendors of such implementations and the
committee.

> The motivation can be that it is more natural for a programmer to use a
> keyword to mark methods as abstract than the " = 0" trick.

The 'trick' has been in the language forever. Claiming that it's more 'natural'
to use a keyword invented after 4 standard revisions have shipped is
a bold claim.

Klaim - Joël Lamotte

unread,
Dec 20, 2013, 11:21:20 AM12/20/13
to std-pr...@isocpp.org, gmis...@gmail.com

On Fri, Dec 20, 2013 at 1:42 PM, <masse....@gmail.com> wrote:
Deprecating the use of " = 0 " in favor of an "abstract" keyword could be a nice addition I think.
The motivation can be that it is more natural for a programmer to use a keyword to mark methods as abstract than the " = 0" trick.
 

I think it would be much simpler to just 
 - add 'abstract' as an alias to =0 in our use case;
 - say that the grouping feature don't accept =0 but do work with 'alias'

It's a bit like typedefs being possibly written as a using declaration, but in one case corresponding to an additional feature (here template alias)
only the alternative "using" is allowed.

Deprecating =0 makes no sense to me, providing a clearer and more useful alternative without deprecating seems far better.
In particular with huge codebases: it's hard to serach for =0, = 0,      =0, int k = 0 etc. 

Sean Middleditch

unread,
Dec 20, 2013, 6:58:47 PM12/20/13
to std-pr...@isocpp.org
On Thursday, December 19, 2013 11:51:32 PM UTC-8, Ville Voutilainen wrote:
On 20 December 2013 03:55,  <gmis...@gmail.com> wrote:
> Another related syntactic change but going in the opposite direction might
> be to allow public: etc. without a colon, for those who prefer to go to be
> verbose and spell out each function in full. .e.g.:
>
> class B {
>   public void f1();
>   private void f2();
> };

I fail to see why we'd do this, since it's a difference of one character.

It's less error prone.  If you just prefix the method with public: then that declaration _and all following ones_ are public until the next access specifier.  It's also an issue when you want to mix member functions of differing privilege levels.

It's not a huge deal by any stretch, but it is certainly more than just "one character" difference and nothing else.

Perhaps not, because I again fail to find sufficient motivation.

It confuses people.  New users get tripped up by it often.  Heck, I still sometimes forget the public specifier and then get bitten by unexpected compile errors.  

> The motivation can be that it is more natural for a programmer to use a 
> keyword to mark methods as abstract than the " = 0" trick. 
The 'trick' has been in the language forever. Claiming that it's more 'natural' 
to use a keyword invented after 4 standard revisions have shipped is 
a bold claim. 

It's hardly only just now being 'invented'.  I even recall reading that Bjarne had planned this change to a keyword in the early days but avoided it to get things shipped and we've been stuck with =0 ever since. 

Deprecating =0 is a bit much now of course, but offering 'abstract' as a synonym is a more open topic I'd think.

Ville Voutilainen

unread,
Dec 20, 2013, 7:14:02 PM12/20/13
to std-pr...@isocpp.org
On 21 December 2013 01:58, Sean Middleditch <sean.mid...@gmail.com> wrote:
>> > class B {
>> > public void f1();
>> > private void f2();
>> > };
>> I fail to see why we'd do this, since it's a difference of one character.
> It's less error prone. If you just prefix the method with public: then that

Based on what evidence? If we add this form of an access specifier,
and then people end up making silly mistakes when they accidentally
use the legacy form, what's the conclusion of what's error-prone and what's
not?

> declaration _and all following ones_ are public until the next access
> specifier. It's also an issue when you want to mix member functions of
> differing privilege levels.

How common are such mixes?

> It's not a huge deal by any stretch, but it is certainly more than just "one
> character" difference and nothing else.

Agreed. It's much more than a "one character difference", it's a fair amount
of work at specifying it and implementing it, for questionable gain.

>> Perhaps not, because I again fail to find sufficient motivation.
> It confuses people. New users get tripped up by it often. Heck, I still
> sometimes forget the public specifier and then get bitten by unexpected
> compile errors.

I wouldn't trade such compiler errors for breaking an imperial boatload
of existing code.

>> > The motivation can be that it is more natural for a programmer to use a
>> > keyword to mark methods as abstract than the " = 0" trick.
>> The 'trick' has been in the language forever. Claiming that it's more
>> 'natural'
>> to use a keyword invented after 4 standard revisions have shipped is
>> a bold claim.
> It's hardly only just now being 'invented'. I even recall reading that
> Bjarne had planned this change to a keyword in the early days but avoided it
> to get things shipped and we've been stuck with =0 ever since.

That doesn't make changing from the current syntax to a new keyword
any more natural.

> Deprecating =0 is a bit much now of course, but offering 'abstract' as a
> synonym is a more open topic I'd think.

Well, it can certainly be discussed. Let's start with people finding a
good name for it.
I find it queasy that the first google search hits and wikipedia hits
describe an
"abstract method" as something that has no implementation. Shall we try "pure"
instead? A "pure function" has a fair amount of history that indicates
it may mean
something completely different than a pure virtual function.

Who do we help with this synonym, then?

gmis...@gmail.com

unread,
Dec 21, 2013, 5:54:34 PM12/21/13
to std-pr...@isocpp.org


On Saturday, December 21, 2013 1:14:02 PM UTC+13, Ville Voutilainen wrote:
On 21 December 2013 01:58, Sean Middleditch <sean.mid...@gmail.com> wrote:
>> > class B {
>> >   public void f1();
>> >   private void f2();
>> > };
>> I fail to see why we'd do this, since it's a difference of one character.
> It's less error prone.  If you just prefix the method with public: then that

Based on what evidence? If we add this form of an access specifier,
and then people end up making silly mistakes when they accidentally
use the legacy form, what's the conclusion of what's error-prone and what's
not?
 
I've made mistakes with the current syntax and I'm sure I'll make mistakes with any new syntax too. I'd say we're not talking about a "must have" feature here as yet, but being pretty open to it as a "nice to have" feature seems reasonable.


> declaration _and all following ones_ are public until the next access
> specifier.  It's also an issue when you want to mix member functions of
> differing privilege levels.

How common are such mixes?

> It's not a huge deal by any stretch, but it is certainly more than just "one
> character" difference and nothing else.

Agreed. It's much more than a "one character difference", it's a fair amount
of work at specifying it and implementing it, for questionable gain.

I think it's more than a one character difference. I agree it's a fair amount of work too. The discussion can't hurt though.

>> Perhaps not, because I again fail to find sufficient motivation.
> It confuses people.  New users get tripped up by it often.  Heck, I still
> sometimes forget the public specifier and then get bitten by unexpected
> compile errors.

I wouldn't trade such compiler errors for breaking an imperial boatload
of existing code.
 
I'm sure nobody will let a proposal through that will break "a boatload of existing code" even if some initial ideas might accidentally imply that. So breaking a boatload of code isn't realistic worry to my mind.

>> > The motivation can be that it is more natural for a programmer to use a
>> > keyword to mark methods as abstract than the " = 0" trick.
>> The 'trick' has been in the language forever. Claiming that it's more
>> 'natural'
>> to use a keyword invented after 4 standard revisions have shipped is
>> a bold claim.
> It's hardly only just now being 'invented'.  I even recall reading that
> Bjarne had planned this change to a keyword in the early days but avoided it
> to get things shipped and we've been stuck with =0 ever since.

That doesn't make changing from the current syntax to a new keyword
any more natural.

What's "natural" is obviously subjective. But I'd bet that preferring "=0" to a real word is a minority view. I'd bet that "most people" would prefer a word rather than something that looks like an assignment expression.

The issue is more that "most people" might not support a change to introduce such a word like "abstract" here, even f they'd prefer it, if that's all it was for, since we have something here already and that's different argument. But I'm pretty sure the word vs =0 debate on it's own would have the word choice win by a significant margin. There is already some support here in this very thread for a word and other languages like java have made that preference. I don't know of any languages other than c++ that has chosen = 0 here and that syntax isn't very reusable.


> Deprecating =0 is a bit much now of course, but offering 'abstract' as a
> synonym is a more open topic I'd think.

Well, it can certainly be discussed. Let's start with people finding a
good name for it.
I find it queasy that the first google search hits and wikipedia hits
describe an
"abstract method" as something that has no implementation. Shall we try "pure"
instead? A "pure function" has a fair amount of history that indicates
it may mean
something completely different than a pure virtual function.

What do you find so "queasy" about "abstract"? In my admittedly brief google attempt I found as much that would support "abstract" as anything else.

Who do we help with this synonym, then?

As part of a package of enhancements (also sold separately) I think these things might add value. So "abstract" as a keyword being used at the class level like other languages, and as  a replacement for "=0" to tidy that up, and in the list as suggested by the OP.

class vehicle abstract  {
public void start(); // Implied abstract.
public void stop(); // Implied abstract.
};
class car : public vehicle { }

Quite what the keywords and syntactic changes are be it, final, pure etc. is , but it'd be nice if they add up to something and fit together collectively and get considered in these contexts as well as how they may help or hinder when code is cut and pasted.

Ville Voutilainen

unread,
Dec 21, 2013, 6:06:16 PM12/21/13
to std-pr...@isocpp.org
On 22 December 2013 00:54, <gmis...@gmail.com> wrote:
>> >> > public void f1();
>> >> > private void f2();
>> >> > };
>> >> I fail to see why we'd do this, since it's a difference of one
>> >> character.
>> > It's less error prone. If you just prefix the method with public: then
>> > that
>> Based on what evidence? If we add this form of an access specifier,
>> and then people end up making silly mistakes when they accidentally
>> use the legacy form, what's the conclusion of what's error-prone and
>> what's
>> not?
> I've made mistakes with the current syntax and I'm sure I'll make mistakes
> with any new syntax too. I'd say we're not talking about a "must have"
> feature here as yet, but being pretty open to it as a "nice to have" feature
> seems reasonable.

Yes? Still, I fail to see why we'd add this particular "nice to have" feature,
meaning I find the motivation for it insufficient. If people wish to provide
additional motivation, that's great, if they don't, I don't see why I'd support
such a "nice to have" feature, and I don't see why I wouldn't oppose it.

>> >> Perhaps not, because I again fail to find sufficient motivation.
>> > It confuses people. New users get tripped up by it often. Heck, I
>> > still
>> > sometimes forget the public specifier and then get bitten by unexpected
>> > compile errors.
>>
>> I wouldn't trade such compiler errors for breaking an imperial boatload
>> of existing code.
> I'm sure nobody will let a proposal through that will break "a boatload of
> existing code" even if some initial ideas might accidentally imply that. So
> breaking a boatload of code isn't realistic worry to my mind.

I don't think it's realistic to discuss changing the access default of classes
from private to public, if that's what people are really after here.

>> That doesn't make changing from the current syntax to a new keyword
>> any more natural.
> What's "natural" is obviously subjective. But I'd bet that preferring "=0"
> to a real word is a minority view. I'd bet that "most people" would prefer a

Given the consequences, I have doubts on that.

> The issue is more that "most people" might not support a change to introduce
> such a word like "abstract" here, even f they'd prefer it, if that's all it
> was for, since we have something here already and that's different argument.

Indeed.

> But I'm pretty sure the word vs =0 debate on it's own would have the word
> choice win by a significant margin. There is already some support here in
> this very thread for a word and other languages like java have made that
> preference. I don't know of any languages other than c++ that has chosen = 0
> here and that syntax isn't very reusable.

For java and other languages, see below.

>> Well, it can certainly be discussed. Let's start with people finding a
>> good name for it.
>> I find it queasy that the first google search hits and wikipedia hits
>> describe an
>> "abstract method" as something that has no implementation. Shall we try
>> "pure"
>> instead? A "pure function" has a fair amount of history that indicates
>> it may mean
>> something completely different than a pure virtual function.
> What do you find so "queasy" about "abstract"? In my admittedly brief google
> attempt I found as much that would support "abstract" as anything else.

I find queasy what I wrote above. An "abstract method" is described by wikipedia
as something that has no implementation, and that's how it is in at
least java, don't
remember the details of eg. c#. That's not the case for a pure virtual function
in C++, they can and often do have implementations, especially for the case
of pure virtual destructors.

David Rodríguez Ibeas

unread,
Dec 23, 2013, 9:46:05 AM12/23/13
to std-pr...@isocpp.org
On Sat, Dec 21, 2013 at 5:54 PM, <gmis...@gmail.com> wrote:
What's "natural" is obviously subjective. But I'd bet that preferring "=0" to a real word is a minority view. I'd bet that "most people" would prefer a word rather than something that looks like an assignment expression.

 
Chances are that if this is changed at all the change would be the '0', not the '='. Currently we have ' = delete' and ' = default'. In these two cases the ' = ' can be read as 'defined as [deleted/defaulted]'. This is not really the same case, as the 'pure' specifier is unrelated to the definition of the function, but rather whether dynamic dispatch can find it or whether it must be overridden by a derived type. While I don't particularly like the idea of 'abstract' I could envision 'virtual void f() = abstract;' as a possibility.

But to be honest I don't think that the current ' = 0' is really hurting anyone. All newcomers to the language will find this described early in any C++ OO tutorial and this is just something you learn. The '0' should not be confused with anything else in any context.

    David

David Krauss

unread,
Dec 23, 2013, 10:09:17 AM12/23/13
to std-pr...@isocpp.org
On 12/23/13 10:46 PM, David Rodríguez Ibeas wrote:
> On Sat, Dec 21, 2013 at 5:54 PM, <gmis...@gmail.com> wrote:
>
>> What's "natural" is obviously subjective. But I'd bet that preferring "=0"
>> to a real word is a minority view. I'd bet that "most people" would prefer
>> a word rather than something that looks like an assignment expression.
>>
>>
> Chances are that if this is changed at all the change would be the '0', not
> the '='. Currently we have ' = delete' and ' = default'. In these two cases
> the ' = ' can be read as 'defined as [deleted/defaulted]'. This is not
> really the same case, as the 'pure' specifier is unrelated to the
> definition of the function, but rather whether dynamic dispatch can find it
> or whether it must be overridden by a derived type. While I don't
> particularly like the idea of 'abstract' I could envision 'virtual void f()
> = abstract;' as a possibility.

If the equals-sign is a liability, and doesn't reflect the newer meaning
related to definition, why keep it in "= abstract"? It's just confusing
that defining a pure virtual function is supported, but not with an
inline definition. (This furthermore makes the pure specifier
incompatible with deduced return type.)

David Rodríguez Ibeas

unread,
Dec 23, 2013, 10:45:47 AM12/23/13
to std-pr...@isocpp.org
On Mon, Dec 23, 2013 at 10:09 AM, David Krauss <pot...@gmail.com> wrote:
If the equals-sign is a liability, and doesn't reflect the newer meaning related to definition, why keep it in "= abstract"? It's just confusing that defining a pure virtual function is supported, but not with an inline definition. (This furthermore makes the pure specifier incompatible with deduced return type.)

I agree in the first account, on the first quick read '= delete' and '= default' came to mind, and 'overrides' and 'final' were left aside. The 'abstract'-like specifier is more related to 'overrides' and 'final' than it is to the former.

Billy O'Neal

unread,
Dec 23, 2013, 1:17:36 PM12/23/13
to std-proposals
This whole thing is patently ridiculous. We have a syntax for declaring things abstract. Creating a new syntax does not allow the programmer to accomplish anything new, and does not make the code in question inherently easier to read. I can see no reason to change it other than saying "abstract" looks prettier, which is a terrible reason to make changes in the core language at this point.

Billy O'Neal
Malware Response Instructor - BleepingComputer.com


gmis...@gmail.com

unread,
Dec 23, 2013, 4:22:17 PM12/23/13
to std-pr...@isocpp.org


On Tuesday, December 24, 2013 7:17:36 AM UTC+13, Billy O'Neal wrote:
This whole thing is patently ridiculous. We have a syntax for declaring things abstract. Creating a new syntax does not allow the programmer to accomplish anything new, and does not make the code in question inherently easier to read. I can see no reason to change it other than saying "abstract" looks prettier, which is a terrible reason to make changes in the core language at this point.

Billy O'Neal

You seem to be forgetting that the "abstract" suggestion I made is in relation to the OP's thread about "Group Member Specifiers". i.e. The OP was suggesting "public, =0:" as a syntax as "a group specififer", probably to avoid a new word.

But pushing "= 0" to that position is ugly and not viable IMHO, where as "public, abstract:" as a "group specifier" is more viable if the OP's idea is going to get any traction, which is what I was trying to help with.

This is the topic of the thread after all, and that context that shouldn't be forgotten here.

So *if* a word (I offered "abstract") instead of = 0 is going to be accepted as a "group specifier", it's only right to float the idea as I did, that it could be also be used in the same place as the "= 0" syntax where it is currently used, because:

* "=0" that is pretty ugly and *isn't easily searchable*.
* "abstract" is a consistent meaning here if we enable it somewhere else. Though will still have to search for both unless you using a conversion too, but that might be viable now.
* *if* OP's proposal is to fly, something is needed, "=0" as a "group specifier" isn't viable.

I don't support " = abstract", I prefer just "abstract" with no =, on the basis that it suggests assignment and doesn't match other languages like c# or java. I think that's reasonable and also because c++ edges both ways with it's specififers like static void f().
There isn't a definite balance either way to my mind. It similarly fits with the other idea of allowing "public void f()" as well as "public: void f();"

I prefer "abstract" over "pure" right now, because pure has other meanings to me and those meanings have appeared in other recent proposals that may well happen. and "abstract" could be used on the class too like some other languages

I don't feel "= 0" will ever be deprecated either any time soon even if this proposal was to fly, just to be triple clear about my opinion on that.

As I said before, none of this is strongly motivating to me, I'm just trying to make the OP's original ideas more viable and be supportive until it's time to conclude the evidence of all this and decide if it is viable in the end.

Right now, I'm thinking this isn't viable as yet, but I'm open to seeing if enough supportive ideas can change that situation..

David Krauss

unread,
Dec 23, 2013, 7:08:26 PM12/23/13
to std-pr...@isocpp.org
On 12/24/13 2:17 AM, Billy O'Neal wrote:
> This whole thing is patently ridiculous. We have a syntax for declaring
> things abstract. Creating a new syntax does not allow the programmer to
> accomplish anything new, and does not make the code in question inherently
> easier to read.

As I just mentioned, an alternative to the pure-specifier would enable
definition at member-declaration scope (making code easier to read), and
restore compatibility with features that require such namely return type
deduction (I can't think of a case where this would be useful for a
virtual function, but it certainly qualifies as something new).

> I can see no reason to change it other than saying
> "abstract" looks prettier, which is a terrible reason to make changes in
> the core language at this point.

There is also my proposal for "not final" and "not override" which
improves regularity, as opposed to "= 0 final" which is valid grammar
but nonsense, and the current lack of a counterpoint to the override
specifier. But, that seems dead.

There are bigger fish to fry right now, but the potential gains are
nonzero. I don't see the downside; beginners will easily grasp the idea
of a keyword synonym to punctuation.

Andrew Tomazos

unread,
Dec 31, 2013, 5:52:53 AM12/31/13
to std-pr...@isocpp.org, gmis...@gmail.com
Thanks for your feedback.  The proposal currently has the desirable property (P) that the syntax and semantics of a specifier are consistent, whether or not they are used in a member declaration or in group member position.  This applies also to pure-specifier.

While I think an argument could be made that a pure or abstract keyword that also implied virtual would have been a better choice for the C++ pure-specifier than =0, and also that override and final should have been in prefix position as full keywords as a decl-specifier - we can't really go back in time and change it, and if we released a new standard that specified that these things be changed, people would just ignore us.

With that given, I think it is more important to preserve P than to try and "half-fix" the specifiers as part of this proposal.  Any additional "aliases" to the specifiers, or any new specifiers, should (a) come from a different proposal; and (b) preserve P.

So:

    class I
    {
    public:
        virtual void f() = 0;
        virtual void g() = 0;
        virtual void h() = 0;
    };

can alternatively be expressed:

    class I
    {
    public virtual = 0:
        void f();
        void g();
        void h();
    };

Most agree, given we cannot change = 0, that this looks good to them.
Reply all
Reply to author
Forward
0 new messages