Using 'override' for a function that has been declared using 'typedef'
Clash Royale CLAN TAG#URR8PPP
up vote
15
down vote
favorite
C++ 11 introduced the 'override' specifier for functions and I find it useful as it makes it explicit that a virtual function is being overridden. However, I can't seem to get it work for a function that has been declared using a typedef.
I understand that 'override' is not a keyword, has it got something to do with that?
The following code illustrates my point:
#include <iostream>
typedef char ReturnsChar();
class Basic
public:
virtual char get_a();
virtual ReturnsChar get_z;
;
char Basic::get_a() return 'a';
char Basic::get_z() return 'z';
class Capitalized : public Basic
public:
// Can override explicitly if I use the normal definition
char get_a() override;
// Compiles if I use the typedef but not 'override'
ReturnsChar get_z;
// Will not compile, but would like to do this
//ReturnsChar get_z override;
;
char Capitalized::get_a() return 'A';
char Capitalized::get_z() return 'Z';
int main()
Basic foo;
Capitalized bar;
std::cout << foo.get_a() << std::endl; // a
std::cout << foo.get_z() << std::endl; // z
std::cout << bar.get_a() << std::endl; // A
std::cout << bar.get_z() << std::endl; // Z
I'm using GNU's g++ 8.2.0 and the error it gives me is
error: expected ';' at end of member declaration
ReturnsChar get_z override;
^~~~~
;
error: âÂÂoverrideâ does not name a type; did you mean âÂÂctermidâÂÂ?
ReturnsChar get_z override;
^~~~~~~~
ctermid
EDIT: To address the comments, I understand this style is unclear. I am more interested about why this won't compile and what exactly 'override' does (especially because it is not a keyword).
As an aside, I feel like typedef-ing functions might be clear in some cases, say:
void (*foo(int x, void (*f)(int)))(int);
That's hard to read, especially if comes up often. I can just typedef that as 'UpdateAddressFunction' and then mentally think of every function of that type as something that 'updates an address'.
c++ c++11 c++14 language-lawyer
 |Â
show 7 more comments
up vote
15
down vote
favorite
C++ 11 introduced the 'override' specifier for functions and I find it useful as it makes it explicit that a virtual function is being overridden. However, I can't seem to get it work for a function that has been declared using a typedef.
I understand that 'override' is not a keyword, has it got something to do with that?
The following code illustrates my point:
#include <iostream>
typedef char ReturnsChar();
class Basic
public:
virtual char get_a();
virtual ReturnsChar get_z;
;
char Basic::get_a() return 'a';
char Basic::get_z() return 'z';
class Capitalized : public Basic
public:
// Can override explicitly if I use the normal definition
char get_a() override;
// Compiles if I use the typedef but not 'override'
ReturnsChar get_z;
// Will not compile, but would like to do this
//ReturnsChar get_z override;
;
char Capitalized::get_a() return 'A';
char Capitalized::get_z() return 'Z';
int main()
Basic foo;
Capitalized bar;
std::cout << foo.get_a() << std::endl; // a
std::cout << foo.get_z() << std::endl; // z
std::cout << bar.get_a() << std::endl; // A
std::cout << bar.get_z() << std::endl; // Z
I'm using GNU's g++ 8.2.0 and the error it gives me is
error: expected ';' at end of member declaration
ReturnsChar get_z override;
^~~~~
;
error: âÂÂoverrideâ does not name a type; did you mean âÂÂctermidâÂÂ?
ReturnsChar get_z override;
^~~~~~~~
ctermid
EDIT: To address the comments, I understand this style is unclear. I am more interested about why this won't compile and what exactly 'override' does (especially because it is not a keyword).
As an aside, I feel like typedef-ing functions might be clear in some cases, say:
void (*foo(int x, void (*f)(int)))(int);
That's hard to read, especially if comes up often. I can just typedef that as 'UpdateAddressFunction' and then mentally think of every function of that type as something that 'updates an address'.
c++ c++11 c++14 language-lawyer
9
That is a really confusing / poor use of atypedef
. That makes it very unclear within the class thatget_z
is a method and not a variable.
â CoryKramer
Aug 31 at 11:27
3
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
1
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
1
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
1
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45
 |Â
show 7 more comments
up vote
15
down vote
favorite
up vote
15
down vote
favorite
C++ 11 introduced the 'override' specifier for functions and I find it useful as it makes it explicit that a virtual function is being overridden. However, I can't seem to get it work for a function that has been declared using a typedef.
I understand that 'override' is not a keyword, has it got something to do with that?
The following code illustrates my point:
#include <iostream>
typedef char ReturnsChar();
class Basic
public:
virtual char get_a();
virtual ReturnsChar get_z;
;
char Basic::get_a() return 'a';
char Basic::get_z() return 'z';
class Capitalized : public Basic
public:
// Can override explicitly if I use the normal definition
char get_a() override;
// Compiles if I use the typedef but not 'override'
ReturnsChar get_z;
// Will not compile, but would like to do this
//ReturnsChar get_z override;
;
char Capitalized::get_a() return 'A';
char Capitalized::get_z() return 'Z';
int main()
Basic foo;
Capitalized bar;
std::cout << foo.get_a() << std::endl; // a
std::cout << foo.get_z() << std::endl; // z
std::cout << bar.get_a() << std::endl; // A
std::cout << bar.get_z() << std::endl; // Z
I'm using GNU's g++ 8.2.0 and the error it gives me is
error: expected ';' at end of member declaration
ReturnsChar get_z override;
^~~~~
;
error: âÂÂoverrideâ does not name a type; did you mean âÂÂctermidâÂÂ?
ReturnsChar get_z override;
^~~~~~~~
ctermid
EDIT: To address the comments, I understand this style is unclear. I am more interested about why this won't compile and what exactly 'override' does (especially because it is not a keyword).
As an aside, I feel like typedef-ing functions might be clear in some cases, say:
void (*foo(int x, void (*f)(int)))(int);
That's hard to read, especially if comes up often. I can just typedef that as 'UpdateAddressFunction' and then mentally think of every function of that type as something that 'updates an address'.
c++ c++11 c++14 language-lawyer
C++ 11 introduced the 'override' specifier for functions and I find it useful as it makes it explicit that a virtual function is being overridden. However, I can't seem to get it work for a function that has been declared using a typedef.
I understand that 'override' is not a keyword, has it got something to do with that?
The following code illustrates my point:
#include <iostream>
typedef char ReturnsChar();
class Basic
public:
virtual char get_a();
virtual ReturnsChar get_z;
;
char Basic::get_a() return 'a';
char Basic::get_z() return 'z';
class Capitalized : public Basic
public:
// Can override explicitly if I use the normal definition
char get_a() override;
// Compiles if I use the typedef but not 'override'
ReturnsChar get_z;
// Will not compile, but would like to do this
//ReturnsChar get_z override;
;
char Capitalized::get_a() return 'A';
char Capitalized::get_z() return 'Z';
int main()
Basic foo;
Capitalized bar;
std::cout << foo.get_a() << std::endl; // a
std::cout << foo.get_z() << std::endl; // z
std::cout << bar.get_a() << std::endl; // A
std::cout << bar.get_z() << std::endl; // Z
I'm using GNU's g++ 8.2.0 and the error it gives me is
error: expected ';' at end of member declaration
ReturnsChar get_z override;
^~~~~
;
error: âÂÂoverrideâ does not name a type; did you mean âÂÂctermidâÂÂ?
ReturnsChar get_z override;
^~~~~~~~
ctermid
EDIT: To address the comments, I understand this style is unclear. I am more interested about why this won't compile and what exactly 'override' does (especially because it is not a keyword).
As an aside, I feel like typedef-ing functions might be clear in some cases, say:
void (*foo(int x, void (*f)(int)))(int);
That's hard to read, especially if comes up often. I can just typedef that as 'UpdateAddressFunction' and then mentally think of every function of that type as something that 'updates an address'.
c++ c++11 c++14 language-lawyer
c++ c++11 c++14 language-lawyer
edited Aug 31 at 16:40
asked Aug 31 at 11:24
Globe Theatre
23018
23018
9
That is a really confusing / poor use of atypedef
. That makes it very unclear within the class thatget_z
is a method and not a variable.
â CoryKramer
Aug 31 at 11:27
3
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
1
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
1
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
1
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45
 |Â
show 7 more comments
9
That is a really confusing / poor use of atypedef
. That makes it very unclear within the class thatget_z
is a method and not a variable.
â CoryKramer
Aug 31 at 11:27
3
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
1
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
1
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
1
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45
9
9
That is a really confusing / poor use of a
typedef
. That makes it very unclear within the class that get_z
is a method and not a variable.â CoryKramer
Aug 31 at 11:27
That is a really confusing / poor use of a
typedef
. That makes it very unclear within the class that get_z
is a method and not a variable.â CoryKramer
Aug 31 at 11:27
3
3
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
1
1
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
1
1
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
1
1
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45
 |Â
show 7 more comments
1 Answer
1
active
oldest
votes
up vote
23
down vote
accepted
I understand that 'override' is not a keyword, has it got something to do with that?
It does: override
is only recognised in a few specific contexts and is available as a name for ordinary use otherwise. However, I believe this is a compiler bug, and this is one context where the compiler should recognise it in its special meaning.
The relevant grammatical production for this is
[class.mem]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
This does not require that a virt-specifier-seq only appear in a declaration containing parameters. The only similar requirement is stated below:
[class.mem]p8:
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
In your case, the declaration is one of a virtual member function. I believe override
should be accepted here.
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I thinkstruct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member namedoverride
.
â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
 |Â
show 5 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
23
down vote
accepted
I understand that 'override' is not a keyword, has it got something to do with that?
It does: override
is only recognised in a few specific contexts and is available as a name for ordinary use otherwise. However, I believe this is a compiler bug, and this is one context where the compiler should recognise it in its special meaning.
The relevant grammatical production for this is
[class.mem]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
This does not require that a virt-specifier-seq only appear in a declaration containing parameters. The only similar requirement is stated below:
[class.mem]p8:
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
In your case, the declaration is one of a virtual member function. I believe override
should be accepted here.
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I thinkstruct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member namedoverride
.
â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
 |Â
show 5 more comments
up vote
23
down vote
accepted
I understand that 'override' is not a keyword, has it got something to do with that?
It does: override
is only recognised in a few specific contexts and is available as a name for ordinary use otherwise. However, I believe this is a compiler bug, and this is one context where the compiler should recognise it in its special meaning.
The relevant grammatical production for this is
[class.mem]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
This does not require that a virt-specifier-seq only appear in a declaration containing parameters. The only similar requirement is stated below:
[class.mem]p8:
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
In your case, the declaration is one of a virtual member function. I believe override
should be accepted here.
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I thinkstruct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member namedoverride
.
â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
 |Â
show 5 more comments
up vote
23
down vote
accepted
up vote
23
down vote
accepted
I understand that 'override' is not a keyword, has it got something to do with that?
It does: override
is only recognised in a few specific contexts and is available as a name for ordinary use otherwise. However, I believe this is a compiler bug, and this is one context where the compiler should recognise it in its special meaning.
The relevant grammatical production for this is
[class.mem]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
This does not require that a virt-specifier-seq only appear in a declaration containing parameters. The only similar requirement is stated below:
[class.mem]p8:
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
In your case, the declaration is one of a virtual member function. I believe override
should be accepted here.
I understand that 'override' is not a keyword, has it got something to do with that?
It does: override
is only recognised in a few specific contexts and is available as a name for ordinary use otherwise. However, I believe this is a compiler bug, and this is one context where the compiler should recognise it in its special meaning.
The relevant grammatical production for this is
[class.mem]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
This does not require that a virt-specifier-seq only appear in a declaration containing parameters. The only similar requirement is stated below:
[class.mem]p8:
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
In your case, the declaration is one of a virtual member function. I believe override
should be accepted here.
answered Aug 31 at 11:36
hvd
113k11194273
113k11194273
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I thinkstruct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member namedoverride
.
â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
 |Â
show 5 more comments
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I thinkstruct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member namedoverride
.
â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
The one catch is [lex.name]/2 "Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier." I don't see a way that code could be ambiguous, but I'm not 100% certain.
â aschepler
Aug 31 at 11:39
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
Thanks, this is very clear. I'm quite pleased that I've discovered an actual compiler bug, that's one to tick off the bucket list!
â Globe Theatre
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I think
struct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member named override
.â hvd
Aug 31 at 11:45
@aschepler Good point. I think there are some similar cases with ambiguities. I think
struct A struct B ; struct B override; ;
might be one, which because of what you quoted declares a non-static data member named override
.â hvd
Aug 31 at 11:45
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
Did you already file some bug reports?
â Rakete1111
Aug 31 at 15:41
2
2
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
@hvd Done: gcc.gnu.org/bugzilla/show_bug.cgi?id=87174
â Rakete1111
Aug 31 at 18:07
 |Â
show 5 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52114447%2fusing-override-for-a-function-that-has-been-declared-using-typedef%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
9
That is a really confusing / poor use of a
typedef
. That makes it very unclear within the class thatget_z
is a method and not a variable.â CoryKramer
Aug 31 at 11:27
3
^ completely agree on that. If you add the language-lawyer tag someone might tell if this is according to the standard or not, but I dont want to see a code review that accepts this :P
â user463035818
Aug 31 at 11:31
1
Yes, in this example I agree completely. However, in my actual use case there are some very complex function prototypes and function pointers that I use, which make typedef-ing of a function useful (I like to think). Either way, the aim of my question is more about understanding why it will not compile, as opposed to style.
â Globe Theatre
Aug 31 at 11:31
1
why not typedef the returntype only? isnt that sufficient?
â user463035818
Aug 31 at 11:32
1
@user463035818 Another bug. A virt-specifier isn't even allowed in the syntax for a regular declaration, only in a member-declaration within a class.
â aschepler
Aug 31 at 11:45