Is `inline;` an invalid declaration or not a declaration at all? - c++

Say I want to know what is a declaration. I go to [dcl.pre] and read that
Declarations have the form
followed by various possible forms, one of which is a simple-declaration, which can, in turn, have the form of decl-specifier-seq init-declarator-list(opt);. given the latter piece is optional, I assume a simple-declaration can have the form of just decl-specifier-seq;. By the same reasoning, I end up understanding that a decl-specifier-seq can have the form of a single decl-specifier; finally, this can be just inline.
If the above reasoning is correct, then I conclude that a line of code containing just inline; is a declaration. But clearly it is not even compilable.
What does this mean? That inline; is a declaration but is an invalid declaration? And that I should understand that from the text? Or what?

Lots of things satisfy the grammar but are nonsense:
int int int i;
1+1+=1;
void(1,2);
*1;
int &*pr;
(1+...);
void f(consteval int);
inline struct S {};
++main;
The proper response to these oddities is not to worry about what they platonically are; the proper response is wat.

Related

Can I declare multiple functions with comma?

Can we use , operator to declare multiple functions once ?
This code compiles on gcc:
void f(), g();
void f() {}
void g() {}
int main() {
f();
}
Is it standard or a particularity of the compiler ?
It's standard. Look at all the things you can declare:
int a, *pa, f(int), *g(int);
This is a single declaration, with a single type specifier int and four declarators. Note that the two variable declarations there have different types, despite having the same type specifier. Same deal with the two function declarations. The type specifier only covers the innermost nugget of the type; the individual declarators wrap it in things like pointers or function-ness.
The function definition int f() { ... } is unique and unusual. While it serves to both declare and define a function, and involves some of the same syntactic constructs as declarations, it is syntactically separate from a declaration. Since a declaration is the thing that gets to have a list of declarators, the function definition syntax doesn't inherit that behavior. So you can declare multiple functions in a single declaration, but a function definition is not a declaration (despite the fact that it declares a function!) so you can only do one at a time.
Editorializing a little: This facet of the syntax, with type information spread between the type specifier and the declarator, is one of the core awfulnesses of C and C++. It dates back to the earliest days of C, when the focus of the language meant that most variables were ints and the type was actually the most optional part of a declaration. Most of us have experienced this in the form of int* a, b only making one pointer, but things like the parentheses that crop up when declaring function pointers, and the overall spiral-ness of complex type definitions, also spring from that essential, never-corrected mistake from the early 1970s.

Isn't a semicolon (';') needed after a function declaration in C++?

I just recently took an intermediate programming test, and one of the questions I got wrong was as follows:
A semicolon (';') is not needed after a function declaration.
True or False.
I chose "false" (and please correct me if I'm wrong because I feel like I'm going crazy), a function declaration is what you write before the definition (at the top of the code) so the compiler knows the function call before even calling it, and a function definition is what makes up the function as a whole.
I.e.,
Declaration:
int func();
Definition:
int func() {
return 1;
}
Shouldn't the answer to this be false?
You can have a situation where you declare and define the function in one step, i.e. if you include the function definition at the point where you're declaring it. So technically I suppose true is correct. But the question is worded in such a way that I would have answered it the way you did.
In addition to the "a definition is also a declaration" thing, the following is legal C++:
int f(), g();
This declares two functions,f and g, both without arguments and with a return type of int, but the definition of f is not followed (immediately) by a semicolon. Likewise, this is legal:
int f(), i = 42;
But it is indeed not allowed to omit the semicolon entirely in these cases, so it would be somewhat surprising if either was taken as an example of a declaration without a following semicolon. In fact, the following is illegal:
void *p, f() {}
Other than a (mere) function declaration, a function definition cannot be combined with any other declaration or definition to the same type-specifier. (If this were legal, it would define both a void *p and a void f() {}.)
In any case, this seems to be a "gotcha" type of question that should not be in an intermediate programming test.
(Oh, by the way, please don't actually write code like int f(), i = 42;.)
The other answers and comments call out several of the many ways that this is a horrid, misleading and badly-written question. But there is another problem that no one else has identified yet. The question is:
A semicolon (';') is not needed after a function declaration. True or False.
OK, let's look at a function declaration:
int func(); /* */
/* ^ */
/* | */
/* That whitespace is "after the function declaration". */
That whole thing is the declaration. The declaration is not int func() and then followed by a ;. The declaration is int func(); and then is followed by whitespace.
So, the question is: is a semicolon needed after the declaration? Of course not. The declaration already has a semicolon in it which terminated it. A semicolon after the declaration would be pointless. By contrast, int func(); ; would be a semicolon after a function declaration.
The question was almost certainly intended to ask the question "true or false: the last token in a function declaration is always a semicolon" But that's not the question that they wrote, because the author of the quiz was not thinking clearly about the problem.
My advice is to avoid programming language quizzes altogether. They're pretty awful.
Fun fact, while we are on the subject. In C#, these are all legal:
class C {}
class D {};
struct E {}
struct F {};
In C#, a class or struct declaration may end in a semicolon, or not, at your discretion. This odd little feature was added for the benefit of C/C++ programmers coming to C# who have it in their fingertips that type declarations end in a pointless semicolon; the design team didn't want to punish them for having this habit. :-)
You can declare a function like this too:
int func(){
return 1;
}
The statement is very ambiguous. The right answer should be: it depends on how you declare the function.
Anyway, I'd have chosen false too, and maybe you can report the question to someone.
A semicolon (';') is not needed after a function declaration.
True or False.
True. A semicolon is not needed after any declaration. Nor after any definition. Nor after any statement.
Many kinds of declaration have to end with a semicolon, as the syntax in section 7 [dcl.dcl] specifies. But there is never any need to write a second one after that.
This depends on whether we are declaring or defining the function.
If we are declaring the the function, we need to include the semicolon (;), and if we are defining the function, the semicolon is not needed.
A declaration is like this:
int add(int, int);
And a definition is like this:
int add(int a, int b)
{
// ...
}
Even though I agree with almost all of the other answers, stating that the question is worded very ambiguous, and that your answer is technically correct, allow me to give a different perspective:
This is how I've always called them:
void func(); // The function prototype
...
void func()
{
// The function definition
}
I'm assuming the question was made up with this terminology in mind.
Definition and declaration are both the same concept in my eyes. "I define x = y" == "I declare x = y".
But of course, there's a big difference between the function prototype (on top) and the actual definition of the function.
It's a pity the question that you took doesn't say "directly after". We could for example write this:
int func() /* My function */ ;
Or I could write:
int func()
int a = 42;
In the first case the semicolon is not directly after the declaration, but that would be OK.
In the second case there is a semicolon "after" the declaration, but not directly after.
I think Eric Lippert has the right idea in his answer.
It's like saying "should there be a period after the end of a sentence in English?". Arguably, a sentence already has a period at the end (otherwise it wouldn't be a sentence) and therefore there should not be a period after the sentence..
You can use ; for prototypes only.
It's kind of a tricky question, but they used the word declaration which means something like this:
int example();
So it's true in this case.
If they'd used the word implementation then it'd been false.
Semicolon (;) is used to tell the compiler that after this semicolon (;) a new statement starts.
So I think the semicolon (;) is required during a function declaration only. So according to me, the answer will be true.
When functions are defined before main():
Don't need semicolon because the function is already defined
When functions are defined after main():
Need semicolon because because you are prototyping that function and telling the compiler that the function exits.

Is "int (x), 1;" an ambiguous statement?

void f(int x) {
int (x), 1;
}
Clang compiles it, GCC doesn't. Which compiler is correct?
IMO, the wording in [stmt.ambig] is clear enough on this:
An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
[Note: If the statement cannot syntactically be a declaration, there is no ambiguity, so this rule does not apply. The whole statement might need to be examined to determine whether this is the case.
The wording speaks of an entire (expression-)statement.
Your statement cannot be parsed as a declaration, because the lexeme 1 is grammatically not a declarator. There is no ambiguity: it might look ambiguous if we looked solely at int(x), but the standard quite explicitly denies that if some prefix of the statement parses as a declaration, the entire statement is considered a potential declaration.
In fact, core experts had a highly similar discussion back in 2002 over core issue 340---I highlighted the important bits. Here, again, we have a supposed declaration that contains an incompatible sub-construct.
Consider the following program:
struct Point {
Point(int){}
};
struct Lattice {
Lattice(Point, Point, int){}
};
int main(void) {
int a, b;
Lattice latt(Point(a), Point(b), 3); /* Line X */
}
The problem concerns the line marked /* Line X */, which is an ambiguous
declarations for either an object or a function. The clause that
governs this ambiguity is 8.2 [dcl.ambig.res] paragraph 1, and reads:
The ambiguity arising from the similarity between a function-style
cast and a declaration mentioned in 6.8 [stmt.ambig] [..]
Based on this clause there are two
possible interpretations of the declaration in line X:
The declaration of latt declares a function with a return value of the
type Lattice and taking three arguments. The type of the first two
arguments is Point and each of these arguments is followed by a
parameter name in redundant parentheses. The type of the third
argument can not be determined, because it is a literal. This will
result in a syntax error.
The declaration of latt declares an object,
because the other option (a function declaration) would result in a
syntax error. Note that the last sentence before the "[Note:" is not
much help, because both options are declarations.
Steve Adamczyk: a number of people replied to this posting on
comp.std.c++ saying that they did not see a problem.
The original
poster replied:
I can't do anything but agree with your argumentation. So there is
only one correct interpretation of clause 8.2 [dcl.ambig.res]
paragraph 1, but I have to say that with some rewording, the clause
can be made a lot clearer, like stating explicitly that the entire
declaration must be taken into account and that function declarations
are preferred over object declarations.
I would like to suggest the following as replacement for the current
clause 8.2 [dcl.ambig.res] paragraph 1:
The ambiguity arising from the similarity between a functionstyle cast
and a declaration mentioned in 6.8 [stmt.ambig] […]
The working group felt that the current wording is clear enough.

Difference between prototype declaration and forward declaration?

So I have this code:
class xx
{
int getnum(); //Is this a forward declaration or a prototype declaration and why?
};
int xx::getnum()
{
return 1+3;
}
So the question has already been commented in the code but:
Is int getnum(); a forward declaration or a prototype declaration and why?
Neither the term "forward declaration" nor "prototype declaration" are defined in the C++ standard, so very strictly speaking, it's neither. It is simply a declaration. If you want to be more specific, you could call it a non-defining declaration, or "a declaration which is not a definition."
When the words "forward declaration" are used in the standard, they are used to refer to declarations which declare, but do not define, the thing (function or class) they declare. Following this usage, int getnum() is therefore a forward declaration.
"Prototype declaration" of a function is used even less in the standard(1), and mostly when talking about [in]compatibility with C. However, when used, it refers to the exact same concept as a forward declaration of that function. Going by this, you could also call int getnum(); a prototype declaration.
To summarise, the terms "forward declaration" and "prototype declaration" have no formal definition, but from the way they are normally used and understood, int getnum(); can be described as either.
(1) However, a similar term "function prototype scope" is defined in the standard (C++17 N4659 [basic.scope.proto] 6.3.4/1). It establishes the scope of function parameter names in a non-defining function declaration, and it's the closest enclosing function declarator.
C++ only allows full prototype declarations of functions, unlike C in which something like int getnum(); could be a forward declaration of something like int getnum(int);
C.1.7 Clause 8: declarators [diff.decl]
8.3.5
Change: In C ++ , a function declared with an empty parameter list takes no arguments. In C, an empty
parameter list means that the number and type of the function arguments are unknown.
Example:
int f(); // means int f(void) in C ++, int f( unknown ) in C
Rationale: This is to avoid erroneous function calls (i.e., function calls with the wrong number or type of
arguments).
Effect on original feature: Change to semantics of well-defined feature. This feature was marked as
“obsolescent” in C.
Difficulty of converting: Syntactic transformation. The function declarations using C incomplete declaration style must be completed to become full prototype declarations. A program may need to be updated further if different calls to the same (non-prototype) function have different numbers of arguments or if the
type of corresponding arguments differed.
A forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
On the other hand a prototype refers to a function not an identifier.
Hope the following clear things out for you!
int getnum(); // Function prototype. You have not yet implemented the body of getnum() function, thus its a forward delcaration.
class RandomClass; // Forward declaration of RandomClass. You have not yet implemented this class but you need it for the rest of your code.
class xx{
RandomClass *foo; // Our need of having a member like that, made us make a forward declaration of the class RandomClass, above class xx
void BarFunction(); // Function Prototype!
};
int getnum(){ //This is the simply the body of your prototype above. Has nothing to do with the classes
return 1+3;
}
void BarFUnction(){
cout << "foo-bar\n" ;
}
Forward declaration is a type of declaration where you specify an Identifier for a Variable, Constant, Type or a Function without giving it's implementation. it actually tells the compiler about an entity with some meta data like name, size etc.
On the other hand, by prototype declaration for a Function means the declaration of a Function with a name and type signature without specifying the function body. So it's only for the function concept, not for variables, constants or types. And so forward declaration can be regarded as a superset of prototype declaration.
For the above example, according to definitions, it's both forward declaration and prototype declaration. Hopefully I am not wrong.

Declaration with multiple declarators - Definition?

Is the following declaration also a definition?
int f(), i = 1;
If we would rewrite it like this only the second declaration would be a definition:
int f();
int i = 1;
The c++ standard seems to apply the term definition to entire declarations, but to me it seems like it should be applied to parts of declarations.
Each declarator is individually considered to define or merely declare its identifier.
f() is only declared. There should be a definition somewhere else.
i is defined. A subsequent declaration would need to use extern to avoid being a redefinition.
§3.1 Declarations and definitions in the C++14 standard says,
A declaration is a definition unless it declares a function without specifying the function’s body, it contains the extern specifier or…
The paragraph goes on and on with quite a few rules and exceptions. It may perhaps be a defect in the standard that it fails to mention declarators there, despite discussing features that do not immediately appertain to entire declarations.
We also have §8/3,
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.
This could be interpreted to override the "contagious" formulation of rules in §3.1/2.
Both of them are equivalent statements. In both cases, it is declaration for the function f() and declaration + definition for the variable i.
This declaration
int f(), i = 1;
contains two declarations and one definition. That is it declares a function and it declares and at the same time defines an object.
A function definition is a function declaration that includes its body. However in the declaration above the function does not includes its body. So it is only a declaration of function f with unknown number of parameters if it is a C declaration or without parameters if it is a C++ declaration..
As for variable i then this declaration is at the same time a definition of the variable because a memory is reserved for the corresponding object of type int and moreover the reserved memory is initialized by integer constant 1.
From the C Standard (6.7 Declarations)
5 A declaration specifies the interpretation and attributes of a set
of identifiers. A definition of an identifier is a declaration for
that identifier that:
— for an object, causes storage to be reserved for that object;
— for a function, includes the function body