Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling std::terminate() vs. std::terminate (no parens) #2150

Closed
jensmaurer opened this issue Jun 10, 2018 · 6 comments
Closed

Calling std::terminate() vs. std::terminate (no parens) #2150

jensmaurer opened this issue Jun 10, 2018 · 6 comments
Assignees

Comments

@jensmaurer
Copy link
Member

[basic.start.term] uses the latter, [except] mostly uses the former. Decide and harmonize.

@jensmaurer jensmaurer added the decision-required A decision of the editorial group (or the Project Editor) is required. label Jun 10, 2018
@tkoeppe
Copy link
Contributor

tkoeppe commented Jun 11, 2018

Can we take a wider look at how we say "call <function-name>" and how we spell that?

@W-E-Brown
Copy link
Contributor

W-E-Brown commented Jun 11, 2018 via email

@zygoloid
Copy link
Member

zygoloid commented Jun 11, 2018

There are multiple issues here:

One issue is naming functions as function() instead of just function, where the trailing parentheses are supposed to merely indicate "that thing was a function" and the function actually takes parameters. That's simply wrong, and we have existing editorial guidance on removing those parentheses. But that's not this case.

For a function that takes no parameters, such as terminate, terminate() could mean two things. One is "the overload of the function terminate that has no parameters". I would strongly prefer that we do not use trailing parentheses on a function name unless it is overloaded. (If a smart pointer has both reset() and reset(pointer) overloads, it's fine to say "reset() does this thing, reset(pointer) does something else". But not for terminate.) That appears to cover most of the uses in [except], which are referring to the function itself, not to a call to the function.

The other thing that terminate() could mean is "the expression terminate()". That usage seems fine to me, and is consistent with how we'd describe a call to a library function that takes arguments. But I don't think (m)any of our uses of terminate() actually mean that.

The phrase "calls blah" is ambiguous, particularly when "blah" ends with parentheses. It could mean either "calls the function named by blah [with no arguments]", or "evaluates the expression blah, which is a function call expression". "Calls terminate" is the former, and "Calls terminate()" is the latter. Both forms are disappointing:

  • When we say "std::terminate is called", we have incompletely specified the behavior. Called with what arguments? We get away with this because there is (currently) no choice, but that would change if an overload were added.
  • When we say "calls std::terminate()", do we mean "evaluates std::terminate()" or do we mean "evaluates std::terminate(), interprets its result as a callable, and then calls that?

Decision:

  • Do not use trailing parentheses to mean simply "this name is a function". You may use trailing parentheses when referring to an overloaded function to specify which overload you mean, but if this comes up we should discuss a better way of naming it, such as "the blah(int) overload".

  • When we say "Calls blah", blah should be an expression that results in a function call. Eg, "calls operator new(size)" or "calls current_exception() and stores the returned value".

  • As an alternative, you may use "Calls blah with <some arguments>", and in that case blah should be a function.

  • The form "Calls to the function blah do X, Y, Z" is also OK, and blah should denote a function not an expression. (Per the first bullet, there should be no parentheses unless the function is overloaded.)

Which I think means that most of the places that say std::terminate without parens are wrong and need parens (eg, in [basic.start.term]), and most of the places that say std::terminate() with parens are wrong and need the parens removed (eg, in [except]).

@zygoloid
Copy link
Member

I also think Walter's suggestion is good. Try not to introduce more uses of "called" when we mean something other than an invocation of a function. In contexts where we can't just use "is", "known as" can be used.

All else being equal, we should endeavor to define terms separately from stating requirements on those terms, allowing use of "is" instead of "known as" or "called". Eg, in [lex.ccon], we have:

A character literal that begins with u8, such as u8’w’, is a character literal of type char, known as a UTF-8 character literal. The value of a UTF-8 character literal is equal to [...]

But we should instead separate the definition from the requirements on the implementation, removing the "known as" in the process:

A UTF-8 character literal is a character literal that begins with u8, such as u8'w'. A UTF-8 character literal is of type char and its value is equal to [...]

@jensmaurer jensmaurer removed the decision-required A decision of the editorial group (or the Project Editor) is required. label Jun 13, 2018
@jensmaurer
Copy link
Member Author

I'd like to point out that "called" (as in function call) is slightly ambiguous whether only calls via function call expressions [expr.call] are in scope, or any situation where a function is invoked (e.g. conversion function, constructor, destructor of temporary at end of full-expression etc.) I thought CWG was eager to use "invoked" in such general circumstances, but a second look at existing text might be worthwhile.

@jensmaurer
Copy link
Member Author

@zygoloid, I believe we should really remove more of the "is called", in particular with std::terminate, since it almost never appears in an expression that the user wrote.

I'd suggest for the std::terminate case in particular, "... the function std::terminate is invoked (except.terminate]". This phrasing avoids the parens question and the "is there really an expression that is evaluated" question (for example, what if std::terminate had a default argument: where would temporaries be destroyed?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants