How to interpret "terms and definitions" in the C++ standard document? - c++

As I study different sections in the C++ standard ( Where do I find the current C or C++ standard documents? ), I would like to refer back to the "Terms and definitions", §1.3.
However, the terms and definitions are provided in a form that I cannot adequately understand or interpret, and there is no explanation given in the text regarding how to interpret them.
Consider the very first term that is defined in the "Terms and definitions" section of the standard:
1.3.1 [defns.argument]
argument
actual argument
actual parameter
<function call expression> expression in the comma-separated list
bounded by the parentheses
What does [defns.argument] refer to?
What is the meaning and purpose of the lines actual argument and actual parameter?
Does <function call expression> refer to a different "term or definition"? If so, it's not defined in the "Terms and definitions" section - why not? If not, what does it refer to? (NOTE: I am not asking what "function call expression" means, because I already know; instead, I am asking how to read and interpret the "Terms and definitions" section of the C++ standard using this simple example.)

What does [defns.argument] refer to?
[defns.argument] is the section tag; it is intended to be used for editorial purposes as it is invariant under section renumbering (e.g. in response to insertion, removal or reordering of sections). It can also be used in referring to the standard, but section numbers (relative to a published version of the standard) are more concise.
What is the meaning and purpose of the lines actual argument and actual parameter?
"actual argument" and "actual parameter" are aliases for the term "argument". You will see below under 1.3.14 [defns.parameter] that "formal argument" and "formal parameter" are aliases for the term "parameter".
The terms "actual argument" and "actual parameter" only appear in [defns.argument]; "formal argument" is described as an alias in 8.3.5p11, and "formal parameter" is used in approximately 13 places, a small fraction of the number of places where "parameter" is used.
Does <function call expression> refer to a different "term or definition"?
The angle-bracketed term is the context in which this definition applies. For example, "argument" has a different meaning in the context of a "function call expression" to in the context of a "function-like macro".

What does [defns.argument] refer to?
That's an alternative way of referring to the section (1.3.1). It should remain the same in future versions of the standard (unless it's removed), while the numbering may change.
What is the meaning and purpose of "actual argument" and "actual parameter"?
They are other terms that you might see, that mean the same thing. I believe that old versions of the spec. used "formal argument" and "actual argument" where the modern spec. uses "parameter" and "argument".
Does <function call expression> refer to a different "term or definition"?
That's the context in which "argument" has this meaning - the following sections give it different meanings in other contexts. Function call expressions are defined in 5.2.2; within such an expression, "argument" means "expression in the comma-separated list bounded by the parentheses".

Related

Is `sizeof(T)` with an incomplete type a valid substitution-failure as per the C++ Standard?

I've seen it come up a few times on StackOverflow and elsewhere that decltype(sizeof(T)) can be used with std::void_t to SFINAE off of whether T is complete or not. This process is even documented by Raymond Chen in Microsoft's blog titled Detecting in C++ whether a type is defined with the explicit comment stating:
I’m not sure if this is technically legal, but all the compilers I tried seemed to be okay with it.
Is this behavior reliable and well-defined as per the C++ standard?
The only indication I can find in the standard is from [expr.sizeof]/1 wherein it states:
... The sizeof operator shall not be applied to an expression that has function or incomplete type, to the parenthesized name of such types, or to a glvalue that designates a bit-field ...
However it is unclear to me whether the wording "shall not be applied" would imply that this is "invalid" for the purposes of substitution as per the rules in [temp], or whether this is ill-formed.
ℹ️ Note: This question is not directed at any particular version of the standard, but it would be interesting to compare if this has changed at any point.
"Shall not be applied" means that it would normally be ill-formed. In an SFINAE context, if something would normally be ill-formed due to resulting in "an invalid type or expression", this becomes a substitution failure, as long as it is in the "immediate context" (C++20 [temp.deduct]/8) and not otherwise excluded from SFINAE (e.g. see p9 regarding lambda expressions).
There is no difference between "invalid" and "ill-formed" in this context. p8 explicitly says: "An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written using the substituted arguments." This wording has been present since C++11. However, in C++03, invalid expressions were not substitution failures. This is the famous "expression SFINAE" feature that was added in C++11, after compiler implementers were sufficiently convinced that they would be able to implement it.
There is no rule in the standard that says that sizeof expressions are an exception to the SFINAE rules, so as long as an invalid sizeof expression occurs in the immediate context, SFINAE applies.
The "immediate context" has still not been explicitly defined in the standard. An answer by Jonathan Wakely, a GCC dev, explains the intent. Eventually, someone might get around to formally defining it in the standard.
However, the case of incomplete types, the problem is that this technique is very dangerous. First, if the completeness check is performed twice in the same translation unit on the same type, the instantiation is only performed once; this implies that the second time it's checked, the result of the check will still be false, because the is_type_complete_v<T> will simply refer to the previous instantiation. Chen's post appears to simply be wrong about this: GCC, Clang, and MSVC all behave the same way. See godbolt. It's possible that the behaviour was different on an older version of MSVC.
Second, if there is cross-translation-unit variance: that is, is_type_complete_v<T> is instantiated in one translation unit and is false, and is instantiated in another translation unit and is true there, the program is ill-formed NDR. See C++20 [temp.point]/7.
For this reason, completeness checks are generally not done; instead, library implementers either say that you are allowed to pass incomplete types to their templates and they will work properly, or that you must pass a complete type but the behaviour is undefined if you violate this requirement, as it cannot be reliably checked at compile time.
One creative way around the template instantiation rules is to use a macro with __COUNTER__ to make sure that you have a fresh instantiation every time you use the type trait, and you have to define the is_type_complete_v template with internal linkage, to avoid the issue of cross-TU variance. I got this technique from this answer. Unfortunately, __COUNTER__ is not in standard C++, but this technique should work on compilers that support it.
(I looked into whether the C++20 source_location feature can replace the non-standard __COUNTER__ in this technique. I think it can't, because IS_COMPLETE may be referenced from the same line and column but within two different template instantiations that somehow both decide to check the same type, which is incomplete in one and complete in the other.)

Difference between name lookup and name binding in C++

In C++, is there a difference between name binding and name lookup in? The working draft C++14 standard (N4296) defines name lookup in (3.4) as
Name lookup associates the use of a name with a declaration (3.1) of that name.
I can't find a definition for name binding in the standard, but the IBM Knowledge Center documentation for their XL C/C++ compiler defines:
Name binding is the process of finding the declaration for each name that is explicitly or implicitly used in a template.
The only distinctions between the two definitions seem to be that (1) name binding refers specifically to a name used in a template and (2) name binding refers to a name, while name lookup refers to the use of a name.
However, Section (13.3) on Overload Resolution in the C++ standard mentions binding frequently, but without defining it. The way 'binding' is used in this context makes it seem that binding refers to the association of an argument with a function parameter.
At first, this definition seems different from either of the other two definitions, thought it fits (broadly) the definition of name lookup if we assume that the name of the function is being bound to its declaration by comparing the types of arguments and parameters. That isn't exactly the sense used in Section (13.3), but I'm trying to make sense of the standard without a proper definition.
In short, if anyone has a good definition of 'name binding' or 'binding', I'd be grateful.
Having read the relevant parts of Wilson & Clark Comparative Programming Languages, I think I have a better understanding of the topic. If I surmise correctly, the term 'binding' covers a gamut of related terms, including name-declaration binding, name–type binding, declaration-reference binding, reference-value binding, and name-value binding.
"Name lookup" seems to be a synonym for name-declaration binding. The other uses of 'binding' in the C++14 standard relate to various combinations of the other varieties of binding.
Please correct me if I'm wrong!

Is the term "method" defined by the C++ Standard?

The term "method" is often used to discuss C++ code. Does the standalone term have a well-defined meaning in C++ or is it ambiguous? Is it acceptable to use the term by itself, or should it be qualified (e.g. a "class method" or "virtual method"), or should it be simply avoided altogether?
The term method is not defined in the C++ standard. The terminology uses member function instead.
Bjarne Stroustrup however defines the term method in his own glossary as virtual member function. So this shows evidence that the term is acceptable.
I would avoid this term entirely, as it is clear what you mean by "member function", but not "method" - that you asked this question is proof enough.
However, normative appearances of the word "method" in the C++14 standard are
In the content list:
17.5 Method of description (Informative)
This is repeated in the title of that section.
[basic.compound]:
These methods of constructing types can be applied recursively;
[cpp.include]
The method by which a sequence
of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined
into a single header name preprocessing token is implementation-defined.
[library.general]
The following subclauses describe the definitions (17.3), method of description (17.5), [..]
In table 32, FLT_EVAL_METHOD is mentioned.
In stage 2 of num_get's do_get:
For arithmetic types, punct.thousands_sep() characters are inserted
into the sequence as determined by the value returned by
punct.do_grouping() using the method described in 22.4.3.1.2
[forwardlist.modifiers]:
Otherwise, inserts sz - distance(begin(), end()) elements at the end of
the list such that each new element, e, is initialized by a method equivalent to calling allocator_traits<allocator_type>::construct(get_allocator(), std::addressof(e), c).
[filebuf.virtuals]:
Behaves according to the description of
basic_streambuf<charT,traits>::uflow(), with the specialization that a
sequence of characters is read from the input with the same method as
used by underflow.
The term is clearly never referring to a "member function".
The C++ standard makes no mention of the term method. It should be noted that the official C++ FAQ does make use of this term, but to describe a virtual function; a simple Google search reveals more occurrences of this term.
I've never seen the term method in an IDE (Visual Studio), but I've seen the term member function. In my opinion method is a 'one size fits all' term.
The term method had been historically used as a synonym of the procedure of an object. Considering, an object has both data and behaviour, it is this behaviour which was referred as method.
Tracing backward, I could find a reference to the usage of the term method when referring to an MIT ALGOL version, AED-0
Quoting wikipedia
MIT ALGOL version, AED-0, linked data structures ("plexes", in that
dialect) directly with procedures, prefiguring what were later termed
"messages", "methods", and "member functions".
Over the years method had been an integral part of Object Oriented Analysis and Design and Object-oriented programming. Now C++ evolved as a procedural language where it extended C a procedural language to have object oriented capabilities. C had the concept of structure, and the data elements were called members. Refer Methods in C++.
To not break the lineage, C++ continued to call the elements of structured and the newer genre class as members.
Now, to differentiate between data and functions, instead of introducing a new terminology, it extended this terminology to call data members and member functions. Member functions which supported dynamic binding were called virtual functions.
So, strictly speaking, official references refrains from using the terminology methods when referring to member functions. The terminology is most prevalent among the people who have a more Object Oriented background. So if you want to remain unambiguous, it is best to use the terminology as
data member
member function
virtual functions
Here my analysis regarding the word method.
I did a scan on official documentation (standards, specifications, etc.) on several programming languages.
http://componentsprogramming.com/using-the-right-terms-method/
Adequate taxonomy (not dependent on any programming languages) will be published in a future article.
Regarding to C++, the correct terminology is: member/non-member function.
Some people use member/free functions.

What does "see below" mean when used as a type or exception specification?

Looking through the C++ standard (current draft http://isocpp.org/files/papers/N3690.pdf, sec 20.8.3 is one such place) and through LLVM's libc++ headers, I've found "see below" used as a type and exception specification. It seems to be used when no type exists, but it seemed strange to use a 2 word phrase for that instead of some sort of valid identifier.
Is it discussed somewhere in the standard or elsewhere? Why/how is it used?
see below is simply a place holder for one of a few possible types which are always described in the following text. For example here:
typedef see below element_type;
1
Type: Ptr::element_type if such a type exists; otherwise, T if
Ptr is a class template instantia-tion of the form SomePointer<T, Args>, where
Args is zero or more type arguments; otherwise, the specialization is ill-formed.
you may subsitute Ptr::element_type or T if SomePointer<T, Args> is valid for see below depending on context.
This form is named a syntactic category and is described in section 1.6 of the same document.

What's the correct term for the '...' token?

Consider printf:
int printf ( const char * format, ... );
What are the terms used to describe the ... and the functions that use it? I've been calling it an ellipsis, but that's like calling & the "ampersand operator."
Variable length parameter list
Edit:
Or, if describing the function itself: Variadic function
Ellipsis notation (, ...) p202 "K+R The C Programming Language"
"Ellipsis" is in fact often the best term here. Sometimes we refer to "arguments passed using the ellipsis" (C++03 8.3.5p2). In the context of figuring out the best overloaded function, an argument can be said to "match the ellipsis" (C++03 13.3.2p2).
printf and other functions like it are often called "variadic functions".
Note: The coming C++0x Standard offers two different ways of declaring and implementing variadic functions (the va_arg way and the template way). But both involve the ellipsis token.
Ellipsis operator is the only term I have heard - it's rare enough (thankfully) that you don't need anything else!
This C++ draft specification refers to it simply as 'ellipsis' and sometimes with a definite or indefinite article, as 'an ellipsis' or 'the ellipsis'.
5.2.2 "Function call" section 6 contains:
A function can be declared to accept fewer arguments (by declaring
default arguments (8.3.6)) or more arguments (by using the ellipsis, ... 8.3.5)
than the number of parameters in the function definition (8.4).
8.3.5 "Functions" section 2 contains:
If the parameter-declaration-clause
terminates with an ellipsis, the
number of arguments shall be equal to
or greater than the number of
parameters that do not have a default
argument.
8.3.6 section 4 contains sample code:
void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow
// a parameter with a default argument
Extra pedantry: section 13.3.3.1.3 ("Ellipsis conversion sequences") refers to "the ellipsis parameter specification". However, as stated in the sample code above, the ellipsis is not, strictly speaking, a parameter. 8.3.5 section 1 explains that, while the ellipsis appears in the parameter-declaration-clause, it follows the parameter-declaration-list.
In addition to "ellipsis" and "variadic function", one also sees the terms "vararg" and "varargs" thrown around. This appears to be an abbreviation for "variable argument list", judging by the language surrounding the (LEGACY) header <varargs.h> in POSIX.
Also, the principle reason that the term "ampersand operator" is not used is that the ampersand can represent either of two different operators, depending on the context, which would make the term ambiguous. This does not occur with the ellipsis; there is no other meaning assigned to it, so using the term "ellipsis" for the token "..." is not like using the term "ampersand operator" for the token "&".
Variadic
Martin and Demian are both right:
The three "." together form a ellipsis (On the Macintosh this is a single special character "...", but not usable for C++)
In C++ an ellipsis is used to define a Variable length parameter list