Reputation: 3845
Why isn't it possible to call a function which takes no arguments with a function call as argument which does not return any value (which IMHO is equivalent to calling a function which takes no arguments with no arguments).
For example:
void foo(void) {...}
void bar(void) {...}
foo(bar())
Don't get me wrong, I know void
is not a value and that it cannot be treated like one.
With my logic it would make sense and it should be possible to do that. I mean, why not? Any argument why that should not be possible?
Upvotes: 14
Views: 10696
Reputation: 179917
I'll add one extra declaration: void baz(int);
Now obviously if an argument with type void
is equal to no arguments, then two arguments, one of which has type void would be equal to one argument (as 0 = 1*x <=> 1 = 1+1*x)
So, obviously this is legal: baz(1, bar());
. But also (since void is "nothing") baz(bar(),1);
.
And we can continue in this sense: baz(bar(), 1, bar());
. After all, "void is nothing".
Either you ban it outright, put in arbitrary restrictions, or you end up allowing ridiculous constructs. I agree with the choice for the first resolution
Upvotes: 0
Reputation: 202535
Don't be misled by the notation. Rather annoyingly, C uses the f(void)
prototype to mean "f
expects no parameters" rather than "f
expects a single parameter of type void
". The notation f()
was kept to mean "the number of parameters that f
expects is not known, so you can call it with any number of parameters you like, and good luck to you". Before ANSI Standard C (aka C89), there was no such thing as a function prototype, and you needed a tool like lint
to protect you against even the most mundane sorts of errors with parameters, such as passing the wrong number of parameters or passing a parameter with a wildly incompatible type.
As to why you can't use the value of a function return void
as a value, or why you can't pass a parameter to a function that expects no parameters, those restrictions are in place to protect you from making the most mundane sorts of errors with parameters.
Upvotes: 2
Reputation: 7421
Let's pretend it works. Can you think of a single hypothetical case where
bar();
foo();
which does precisely the same thing isn't vastly more readable and sensible?
Edited. Yes, yes. :)
Upvotes: 0
Reputation: 320551
If the (void)
parameter list was treated uniformly with all other parameter lists in C/C++, the semantic meaning if such parameter declaration would be "a single parameter of type void
". If that was the case, it is quite possible that for the purposes of uniformity the language would allow to "chain" the calls to such functions as shown in your example. (At least C++ probably would, since it allows this kind of uniformity in return
statements).
However, in C++ language as well as in C, parameter list that has the form (void)
is not treated uniformly with other forms of parameter lists. Instead, it has a special meaning. It means that the function has no parameters at all. (Equivalent to empty ()
in C++).
In other words, the function declared with (void)
parameter list takes zero parameters. You are supplying one. This is what makes it illegal. Considering the special meaning of (void)
parameter list in C/C++, allowing
foo(bar());
would not be much different from allowing
foo(bar(), bar());
foo(bar(), bar(), bar());
as well. Qualitatively, 2 and 3 are as much different from 0, as 1 is.
Upvotes: 2
Reputation: 137830
Because, according to paragraph 3.9.1/9 of the standard,
An expression of type void shall be used only as an expression statement (6.2), as an operand of a comma expression (5.18), as a second or third operand of ?: (5.16), as the operand of typeid, or as the expression in a return statement (6.6.3) for a function with the return type void.
C/C++ just isn't designed to be that generic. You do get return returns_void();
for tail-call optimization, that's functional-ish, right? :vP
Edit: The above rule would still allow you to call takes_void(3)
with 3
converted to void
. This is forbidden by 8.3.5/2:
If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list. Except for this spe- cial case, void shall not be a parameter type (though types derived from void, such as void*, can).
Upvotes: 3
Reputation: 76541
At the moment i have something like this in my code: #define EVAL(f) f(++evalcounter) Dont ask me why i use it, i just have to. Normally f does not take any values. I just added this (global) integer just to count something. Wouldnt it be much better if i had something like #define EVAL(f) f( dummy(++evalcounter) ) ?
Have you tried the comma operator:
#define EVAL(f) (++evalcounter, f())
Upvotes: 0
Reputation: 223083
I'm not convinced that any of the reasons I've heard are good ones.
See, in C++, you can return a void
function's result:
void foo() {
// ...
}
void bar() {
// ...
return foo();
}
Yes, it's exactly the same as:
foo();
return;
but is much more consistent with generic programming, so that you can make a forwarding function work without having to worry about whether the function being forwarded has void
return.
So, if a similar system applied so that a void
return constituted a nullary call in a function composition scenario, that could make function composition more generic too.
Upvotes: 8
Reputation: 19247
it does make kind of sense (bar
produces nothing, foo
consumes nothing, therefore foo(bar())
should be allowed). OTOH, it would only be good to confuse the reader. if you want to be l33t, there's always ,
, &&
and ||
operators to emulate semicolons.
Upvotes: 1
Reputation: 798764
Because void
doesn't allow you to specify an argument name, which would be required in order to capture the return value of the first function, regardless of what it actually returned.
Upvotes: 0