Skip to content

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

Closed
@jensmaurer

Description

@jensmaurer
Member

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

Activity

added
decision-requiredA decision of the editorial group (or the Project Editor) is required.
on Jun 10, 2018
tkoeppe

tkoeppe commented on Jun 11, 2018

@tkoeppe
Contributor

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

W-E-Brown

W-E-Brown commented on Jun 11, 2018

@W-E-Brown
Contributor
zygoloid

zygoloid commented on Jun 11, 2018

@zygoloid
Member

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

zygoloid commented on Jun 11, 2018

@zygoloid
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 [...]

removed
decision-requiredA decision of the editorial group (or the Project Editor) is required.
on Jun 13, 2018
jensmaurer

jensmaurer commented on Jun 14, 2018

@jensmaurer
MemberAuthor

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

jensmaurer commented on Jun 15, 2018

@jensmaurer
MemberAuthor

@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?)

self-assigned this
on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @zygoloid@W-E-Brown@tkoeppe@jensmaurer

      Issue actions

        Calling std::terminate() vs. std::terminate (no parens) · Issue #2150 · cplusplus/draft