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.
Related
From § 8.3.5.11 of ISO/IEC 14882:2011(E):
A typedef of function type may be used to declare a function but shall not be used to define a function
The standard goes on to give this example:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
What motivates this rule? It seems to limit the potential expressive usefulness of function typedefs.
Though this question is about C++, but since C++ inherits typedef and function pointer from C, so an explanation of the same question in C can be used in here. There's a formal explanation for C.
Rationale for International Standard - Programming Languages C §6.9.1 Function definitions
An argument list must be explicitly present in the declarator; it cannot be inherited from a typedef (see §6.7.5.3). That is to say, given the definition:
typedef int p(int q, int r);
the following fragment is invalid:
p funk // weird
{ return q + r ; }
Some current implementations rewrite the type of, for instance, a char parameter as if it were declared int, since the argument is known to be passed as an int in the absence of a prototype. The Standard requires, however, that the received argument be converted as if by assignment upon function entry. Type rewriting is thus no longer permissible.
It's probably mostly historical reasons. typedef was a relatively late addition to C, and was tacked onto the existing language (and caused a few problems for the parsing phase of compilers).
Also, a function definition has to define the names of the parameters, if any. A function type includes the function's return type and parameter types, but not its parameter names. For example, these:
void (int)
void (int x)
void (int y)
are three ways of writing the same function type. If you had:
typedef void func_t(int);
then this hypothetical definition:
func_t some_func { }
wouldn't define a name for its int parameter. I'm not sure how that could have been resolved in a reasonable manner. It would be possible, I suppose, but it was never done.
But the bottom line is probably just that Dennis Ritchie either didn't think it was worth the effort to define how a typedef could be used in a function definition, or he simply didn't think of it.
Let me put a few words. Consider a statement:
typedef void F(int p1, char* p2);
This statement assigns name F to a function signature void (int, char*); This is definition of an alias to the function signature. After that the statement:
F fv;
tells that there is a function fv. It has the signature that was mentioned above and it has its body somewhere. Look at the C/C++ syntax of the function definition:
retType funcName(params) { body }
There are actually 2 names used retType and funcName. None of them are the same to the name F from the initial typedef. The name F has meaning of both names. If language would allow something like:
F { body }
this will associate body with the function type. But this leads a problem:
The meaning of F would be not clear. Is it an "alias to the function signature" or is it a "name of the entry point into a code"?
Plus the syntax of the last example would be weird to millions of C/C++ programmers.
The rule is as you quoted - typedef of function type shall not be used to define a function. In the 3rd line of the example, you are trying to define a function with function type F. This is not allowed by the standard.
EDIT
As you pointed out, I try to explain more on it.
For the 3rd line, if it were legal, then you could replace F with the typedef definition:
void fv { }(). This is not a legal definition or declaration in C++.
I think the key point is that typedef is just creating an alias for simplification, and you can replace your typedef type like replacement of #define during compilation.
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.
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
From § 8.3.5.11 of ISO/IEC 14882:2011(E):
A typedef of function type may be used to declare a function but shall not be used to define a function
The standard goes on to give this example:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
What motivates this rule? It seems to limit the potential expressive usefulness of function typedefs.
Though this question is about C++, but since C++ inherits typedef and function pointer from C, so an explanation of the same question in C can be used in here. There's a formal explanation for C.
Rationale for International Standard - Programming Languages C §6.9.1 Function definitions
An argument list must be explicitly present in the declarator; it cannot be inherited from a typedef (see §6.7.5.3). That is to say, given the definition:
typedef int p(int q, int r);
the following fragment is invalid:
p funk // weird
{ return q + r ; }
Some current implementations rewrite the type of, for instance, a char parameter as if it were declared int, since the argument is known to be passed as an int in the absence of a prototype. The Standard requires, however, that the received argument be converted as if by assignment upon function entry. Type rewriting is thus no longer permissible.
It's probably mostly historical reasons. typedef was a relatively late addition to C, and was tacked onto the existing language (and caused a few problems for the parsing phase of compilers).
Also, a function definition has to define the names of the parameters, if any. A function type includes the function's return type and parameter types, but not its parameter names. For example, these:
void (int)
void (int x)
void (int y)
are three ways of writing the same function type. If you had:
typedef void func_t(int);
then this hypothetical definition:
func_t some_func { }
wouldn't define a name for its int parameter. I'm not sure how that could have been resolved in a reasonable manner. It would be possible, I suppose, but it was never done.
But the bottom line is probably just that Dennis Ritchie either didn't think it was worth the effort to define how a typedef could be used in a function definition, or he simply didn't think of it.
Let me put a few words. Consider a statement:
typedef void F(int p1, char* p2);
This statement assigns name F to a function signature void (int, char*); This is definition of an alias to the function signature. After that the statement:
F fv;
tells that there is a function fv. It has the signature that was mentioned above and it has its body somewhere. Look at the C/C++ syntax of the function definition:
retType funcName(params) { body }
There are actually 2 names used retType and funcName. None of them are the same to the name F from the initial typedef. The name F has meaning of both names. If language would allow something like:
F { body }
this will associate body with the function type. But this leads a problem:
The meaning of F would be not clear. Is it an "alias to the function signature" or is it a "name of the entry point into a code"?
Plus the syntax of the last example would be weird to millions of C/C++ programmers.
The rule is as you quoted - typedef of function type shall not be used to define a function. In the 3rd line of the example, you are trying to define a function with function type F. This is not allowed by the standard.
EDIT
As you pointed out, I try to explain more on it.
For the 3rd line, if it were legal, then you could replace F with the typedef definition:
void fv { }(). This is not a legal definition or declaration in C++.
I think the key point is that typedef is just creating an alias for simplification, and you can replace your typedef type like replacement of #define during compilation.
Is it possible to prevent overloading of user defined functions in C++? Suppose I have a function as:
void foo(int , int);
Can I prevent foo from being overloaded, and if so how? If I can, can this be extended to prevent overriding of the methods through inheritance?
In a word: no. You can't prevent an overload of foo being defined with a different signature somewhere else and you also can't prevent virtual functions from being overriden.
In the C++ world you have to give some degree of trust to people writing code that winds up in your program.
Section 13.1.1 through 13.1.3 of the standard describe the kinds of functions that can not be overloaded:
Certain function declarations cannot be overloaded:
Function declarations that differ only in the return type cannot be overloaded.
Member function declarations with the same name and the same parameter types cannot be overloaded if any of them is a static member function declaration (9.4).
Note: as specified in 8.3.5, function declarations that have equivalent parameter declarations declare the same function and therefore cannot be overloaded:
Parameter declarations that differ only in the use of equivalent typedef “types” are equivalent. A typedef is not a separate type, but only a synonym for another type (7.1.3).
Parameter declarations that differ only in a pointer * versus an array [] are equivalent. That is, the array declaration is adjusted to become a pointer declaration (8.3.5). Only the second and subsequent array dimensions are significant in parameter types (8.3.4).
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.
Two parameter declarations that differ only in their default arguments are equivalent.
Otherwise, the function can be overloaded, and there is no way to prevent that.
You cannot.
Make it a static function in a class and tell people not to modify that class?
This can be simulated by making it a struct instance:
struct foo_t {
void operator()(int, int);
} foo;
// error: redefinition of 'foo' as different kind of symbol
void foo(double, double);
or a function reference:
void foo_impl(int, int);
auto const& foo = foo_impl;
// error: redefinition of 'foo' as different kind of symbol
void foo(double, double);
Do what UncleBens said, and include in the class a constant which is an encrypted checksum of the text in the class, and a function to test it for validity. That way, nobody can change the class. Just a thought (maybe not a very good one).
As I think about it, that's pretty dumb because the class would need its own text. However, as an alternative, it could read its compiled binary code, and have a checksum for that. I'm getting out on a limb here.
The only reasonable way would be to give the function C linkage:
extern "C" void foo(int , int);
This works because with C linkage, names aren't mangled, so you can't do any overloading (which relies on encoding the types of arguments into the symbol name).
Obviously this won't extend to member functions.