Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the syntax specifications (keyword/context keyword ordering) for c++ function signatures?

Tags:

c++

The riches of c++ expressiveness and syntax, make it somewhat difficult to use multiple features of the language on a single signature.

For example I'd like to declare a member function[1] as being :

  • virtual
  • override // example of a context keyword
  • noexcept
  • const
  • having a trailing return type

It gets more complicated if we consider that functions can also be

  • defaulted
  • deleted
  • final (for virtual methods)
  • templates
  • explicit specializations
  • [[deprecated]]
  • ... and many many more I can't know/suspect right now

The standard's wording looks Greek to me and even that was not true, I can't know what works with what (or what's a syntactic mishap, eg [1] might even be illegal).

I know that reading individual features (override, noexcept etc) will help, but is there a guide on how to use them in coaction ? (syntactically speaking; I don't expect/want an answer on the functionallity of the features)

EDIT

Just in case it helps, I think the excerpt to be deciphered is the following

8.4.1 Function definitions have the form

function-definition: attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body

like image 743
Lorah Attkins Avatar asked Oct 19 '25 15:10

Lorah Attkins


1 Answers

If you have a copy of the spec, you can look for the grammar in each section. It sounds like you want a complete guide to what is and is not correct, and the spec is the only real source for this information. Fortunately, it's not that difficult to read, it's just time-consuming and tedious.

Here is the grammar for function definitions, taken from the beginning of section 8.4.1 of N3690. I suggest reading a primer on context-free grammars first (Wikipedia - skip to the examples). Note that everybody has their own variation on how they write context-free grammars, so the grammar in the C++ spec will be a little different from what you see in, say, Wikipedia or a compilers textbook.

function-definition:
    attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body
function-body:
    ctor-initializeropt compound-statement
    function-try-block
    = default ;
    = delete ;

Reading this, we see that "function-body" has four alternatives, one on each line. Two alternatives = delete and = default, so those go in the same place that a { ... } more interesting function body would go. (The function try block is a bit of an obscure way of defining a function in C++, so let's just ignore it.)

For "function-definition", you can see it has one line, so there is only one way to define a function. Each item in the line has to appear in order. Parts with the "opt" subscript are optional. So,

  1. Attributes first
  2. Declaration specifiers next (e.g., static, int, extern...)
  3. Declarators after that (e.g. function_name(int x, int y) -> int)
  4. Virtual specifier after that (override or final)
  5. Function body last (this includes normal function bodies { ... } as well as = delete and = default)

Once you have a little practice reading CFGs, it becomes second nature. The only hard part is jumping around the C++ spec to find all of the definitions you want.

Notes

Also note that the grammar will only tell you the syntax. If you just read the grammar, you'll write nonsense like:

// permissible, according to the grammar
extern static const void long short int int x;

Reading the text will explain that you can't, e.g., have a short long, even though it's permitted by the grammar.

The other trick is finding the definition you're looking for. As Serthy asks below, how do you specify pure functions? Where does = 0 go? Well, you can find that = 0 appears in section 9.2 as pure-specifier, but it can only appear on a member-declarator. So it can't appear in function-definition, it can only appear in a "declaration". The declaration and definition syntax is slightly different.

In other words, you can't define a pure function, but you can declare a pure function.

Further reading

If you are interested in this subject, I recommend Compilers: Principles, Techniques and Tools by Alfred V. Aho, Ravi Sethi and Jeffrey D. Ullman.

like image 126
Dietrich Epp Avatar answered Oct 21 '25 06:10

Dietrich Epp