When compiling in C++ I often end up with error messages dealing with "formal parameters", such as
error C2719: 'b': formal parameter with __declspec(align('16')) won't be aligned
I do understand the error, and the fact that b is a parameter of a function I am defining.
However, what does it mean that a parameter is formal? Can there be informal parameters as well?
I do notice that the term "formal parameter" appears in other languages as well, so I presume it is a more generic term not necessarily specific to C-family of languages? Are informal parameters supported by some subset of languages?
Upon seeing the answers, one final question: Where those names formal parameter and actual parameter origin from? Does it origin from the C standard, or is it an effect of calling it as such in some abstract language calculus?
There are formal and actual parameters:
void foo(int arg); //arg is a formal parameter
int main()
{
int val = 1;
foo(val); //val is an actual parameter
}
From C++ Standard:
1.3.1 formal parameter (parameter)
an object or reference declared as part of a function declaration or
definition, or in the catch clause of an exception handler, that
acquires a value on entry to the function or handler; an identifier
from the comma-separated list bounded by the parentheses immediately
following the macro name in a function-like macro definition; or a
template-parameter. Parameters are also known as formal arguments or
formal parameters.
1.3.10 actual parameter (argument)
an expression in the comma-separated list bounded by the parentheses
in a function call expression, a sequence of preprocessing tokens in
the comma-separated list bounded by the parentheses in a function-like
macro invocation, the operand of throw, or an expression, type-id or
template-name in the comma-separated list bounded by the angle
brackets in a template instantiation. Also known as an actual argument
or actual parameter.
Formal parameters are the parameters known at the function definition. The actual parameters are what you actually (hence the name) pass to the function when you call it.
void foo( int a ); // a is a formal parameter
foo(10); // 10 is the actual parameter
It's a matter of being a little pedantic over terminology, but quite useful: The formal parameters are what you just think of function parameters:
int foo(bool a, float b);
Here a and b are formal parameters. The point is that in the function body, you're referring to those parameters "formally" without actually knowing their value. It is only when you actual evaluate a function call expression that the formal function parameters are bound to the function call arguments:
int result = foo(false, 1.5);
In this call expression, the value false of the first argument is bound to the formal parameter a, and similarly for the second argument.
The distinction between parameters and arguments is maybe more important to language designers and comiler writers, but as an example in C++, it can be very helpful to get your head around this when you're trying to follow the rules for template argument deduction.
Related
Consider these two function definitions:
void foo() { }
void foo(void) { }
Is there any difference between these two? If not, why is the void argument there? Aesthetic reasons?
In C:
void foo() means "a function foo taking an unspecified number of arguments of unspecified type"
void foo(void) means "a function foo taking no arguments"
In C++:
void foo() means "a function foo taking no arguments"
void foo(void) means "a function foo taking no arguments"
By writing foo(void), therefore, we achieve the same interpretation across both languages and make our headers multilingual (though we usually need to do some more things to the headers to make them truly cross-language; namely, wrap them in an extern "C" if we're compiling C++).
I realize your question pertains to C++, but when it comes to C the answer can be found in K&R, pages 72-73:
Furthermore, if a function declaration does not include arguments, as
in
double atof();
that too is taken to mean that nothing is to be assumed about the
arguments of atof; all parameter checking is turned off. This special
meaning of the empty argument list is intended to permit older C
programs to compile with new compilers. But it's a bad idea to use it
with new programs. If the function takes arguments, declare them; if
it takes no arguments, use void.
C++11 N3337 standard draft
There is no difference.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Annex C "Compatibility" C.1.7 Clause 8: declarators says:
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.
8.5.3 functions says:
4. The parameter-declaration-clause determines the arguments that can be specified, and their processing, when
the function is called. [...] If the parameter-declaration-clause is empty, the function
takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
C99
As mentioned by C++11, int f() specifies nothing about the arguments, and is obsolescent.
It can either lead to working code or UB.
I have interpreted the C99 standard in detail at: https://stackoverflow.com/a/36292431/895245
In C, you use a void in an empty function reference so that the compiler has a prototype, and that prototype has "no arguments". In C++, you don't have to tell the compiler that you have a prototype because you can't leave out the prototype.
What is the difference between the two declarations in case of foo's arguments? The syntax in the second one is familiar to me and declares a pointer to function. Are both declarations fully equivalent?
void foo(int(int));
void foo(int(*)(int));
They are equivalent as long as int(int) and int(*)(int) are used in function parameter lists. In function parameter list the int(int) is automatically adjusted by the language to mean int(*)(int).
It is the same adjustment mechanism that makes int [] parameter declaration equivalent to int * parameter declaration.
Outside of this specific context int(int) and int(*)(int) mean two different things.
I got a code like this
int def_function(typeA *, double &) {}
Could you please explain what is the meaning of these variables, why they have types but do not have name?
The method signature says that there is a function name def_function which take two parameters of type 'pointer of typeA ' and 'reference of double' . The name of parameter variables are optional but if there is no name then in function definition you can't refer or use any of these variables. So if you are not using those variables in your function you can omit parameter name otherwise it is required.
int def_function(typeA *, double &)
In this function, none of the arguments are used. So that there is no need to name them.
Meaning of those variables are:
typeA * pointer to an object of type typeA
double & reference of an object of type double. Means that, a "double" will be passed by its non-const reference, i.e. it may be changed.
C++14 standard section 8.3.5.11 says that:
An identifier can optionally be provided as a parameter name; if
present in a function definition (8.4), it names a parameter
(sometimes called “formal argument”). Note: In particular, parameter
names are also optional in function definitions and names used for a
parameter in different declarations and the definition of a function
need not be the same.
Remember this is different in C. In C it is mandatory to give a name to formal. parameter.
C99 standard says that:
[6.9.1.5] If the declarator includes a parameter type list, the
declaration of each parameter shall include an identifier, except for
the special case of a parameter list consisting of a single parameter
of type void, in which case there shall not be an identifier.
You have to name the function arguments at function definition and when you use these variables.
You don't have to name the arguments at function declaration if it's defined later.
You don't have to name arguments that you are not using.
In C++11 the following function declaration:
int f(void);
means the same as:
int f();
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
I get the (perhaps false) impression this is an old feature, perhaps inherited from C?
Does anyone know the history or rationale behind this way to declare a function with no parameters?
In C++ they both mean the same thing.
In C f(void) is different from f(), becuse f() means "unspecified parameters" - you can legally pass anything (whether the function at receiving the data is happy about that or not is another matter).
In C++ both are the same thing.
In C, f() means that we don't know how many parameters the function takes at this point. It is unspecified parameters. And f(void) means that this function does not take any parameters.
From the C standard :
6.7.6.3 Function declarators (including prototypes)
6/ A parameter type list specifies the types of, and may declare identifiers for, the
parameters of the function.
10/ The special case of an unnamed parameter of type void as the only item in the list
specifies that the function has no parameters.
14/ An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
And like you said, in the C++ standard :
8.3.5 Functions [dcl.fct]
4/ The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called. [ Note: *the parameter-declaration-clause* is used to convert the arguments specified on the function call; see 5.2.2. —end note ] If the parameter-declaration-clause is empty, the function takes no arguments. A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
This comes to C++ from C. In C f() means unknown number and type of parameters. So in C for no parameters there is f( void ).
In C++ it's redundant: f() and f( void ) mean same thing - a function that has no parameters.
From "A History of C++" (1979− 1991 by Bjarne Stroustrup) at p11:
C with Classes introduced the notation f(void) for a function f that
takes no arguments as a contrast to f() that in C declares a function
that can take any number of arguments of any type without any type
check.
It says later, however, that soon the empty function declarator was given its obvious meaning and the new construct - kinda rendered obsolete for the time. I guess nobody has bothered removing it after (or maybe there had been already some C++ code written with it that have needed support).
In C:
This construct however rendered important role as of the standardization of the C language where function prototyping was borrowed directly from C++. In this case f(void) was useful in supporting existing C code (in which the notion f() was already reserved as to indicate a function taking unspecified number of arguments).
Before that the C language hadn't been able to attach specific types to each parameter but only functions with unspecified number of arguments and with unspecified types were declarable using the f() form.
In C++, there is no difference. However, this is inherited from C, where int f() mean "function which can take any number of arguments of any types" and int f(void); specifies functions that takes no arguments.
Edit As Angew pointed out, in C, f() means "function whose parameters are unknown at this point." It does not mean it can take any number of arguments - close to that would be f(T arg, ...), where arg is at least one named parameter before ..., which accepts at least one argument, arg (as pointed by #hvd).
I am trying to use a function with a default argument as a function pointer template parameter:
template <void (*F)()>
class A {};
void foo1(int a = 0) {}
void foo2() {}
int main()
{
//A<foo1> a1; <-- doesn't work
A<foo2> a2;
}
The compiler error is:
main.cpp:7:7: error: could not convert template argument ‘foo1’ to ‘void (*)()’
Is there specific syntax for this to work? Or a specific language limitation? Otherwise, the alternative is to have two separate functions instead of a default parameter:
void foo1(int a) {}
void foo1() { foo1(0); }
Update
I understand that the signatures are different, but I'm wondering if there is a way to make this work conveniently without needing to modify all the functions with default parameters?
The signature of foo1 is void(int), not void(). This is why it isn't convertible to void(*)().
You are confusing default arguments with overloading.
According to section 8.3.6 of the C++ standard,
If an expression is specified in a parameter declaration this expression is used as a default argument. Default arguments will be used in calls where trailing arguments are missing.
Since A<foo1> is not a call of the function, default arguments are ignored. In fact, they are ignored in all contexts except the calls of the function, for example
typedef void (*FFF)();
FFF x = foo1;
will not compile, and produce the same message that you get when trying to use foo1 as a template parameter:
error: invalid conversion from ‘void (*)(int)’ to ‘void (*)()’
This makes sense, because evaluating default arguments is a separate step in the invocation:
8.3.6.9: Default arguments will be evaluated each time the function is called.
The presence of default arguments does not alter the signature of your function. For example, you cannot use a single-argument function with a default argument to override a no-argument virtual member function.
Default argument values are not part of the function type. You can't use foo1 as a function taking no arguments, because it does take one argument. The argument gets filled in for you if you don't mention it, but it's still there.
Your workaround involving a dispatching function sounds like a good solution. It could even be templated if you need it a lot.
I'm pretty sure that a function pointer has signature of the function with all default parameters expanded and function pointers cannot convert to a function pointer with a different signature. Finding this in the standard is a different matter, though...
I think the relevant clause from the standard is 8.3.5 [dcl.fct] paragraph 6:
... The return type, the parameter-type-list, the ref-qualifier, and the cv-qualifier-seq, but not the default arguments (8.3.6) or the exception specification (15.4), are part of the function type. [ Note: Function types are checked during the assignments and initializations of pointers to functions, references to functions, and pointers to member functions. —end note ]
Note that default arguments are the guys of the form = value according to 8.3.6 [dcl.fct.default] paragraph 1:
If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument. ...
It won't compile because foo1 has signature:
void foo1(int a);
which you're trying to stick into a pointer to:
void F()
The function signatures don't match. The fact that foo1 has a default parameter doesn't change the function's signature (it still can take in an int).
A More Generic Solution
I'd say forget about the templates, they're only limiting you here.
Personally, the way I solve the callback problem is using function objects with argument binding. It can be done using the boost::function library, and binding default arguments with boost::bind (or std::bind1st and std::bind2nd).
These boost libraries are also built-in to the new C++11 standard, as std::function, and std::bind.
It's well worth taking a look at this, as it let's you do some very nice things, like providing default arguments to functions, or use class member functions as callbacks.
The sites I've linked to all have lots of example code, and the boost links have tutorials.