Is the Most Vexing Parse rooted in the ambiguity about whether or not to use void
as the parameter of a function declaration that takes no arguments?
As an example, the following code compiles without error, and runs fine, on both the g++ (v7.2.1) and Xcode (Apple LLVM version 7.0.2 (clang-700.1.81)) compilers.
#include <iostream>
int asdf(void);
int asdf(int a) {
return a;
}
int main() {
std::cout << asdf(6) << std::endl; //-> 6
return 0;
}
This goes all the way back to the ANSI-C standard and before, where an empty parameter list indicated an arbitrary number of arguments. It haunts us today with backward-compatibility in the compilers, that seem to be a bit confused about the issue. Should the above not at least generate a warning, if not throw an error?
Here I had an epiphany (or perhaps a pipe dream!). Could it be that The Most Vexing Parse is rooted in the ambiguity about the use of void
in an empty function declaration list?
Another example, Referencing the following Wikipedia example:
class Timer {
public:
Timer();
};
class TimeKeeper {
public:
TimeKeeper(const Timer& t);
int get_time();
};
int main() {
TimeKeeper time_keeper(Timer());
return time_keeper.get_time();
}
The line
TimeKeeper time_keeper(Timer());
is seemingly ambiguous, since it could be interpreted either as
- a variable definition for variable time_keeper of class TimeKeeper, initialized with an anonymous instance of class Timer or
- a function declaration for a function time_keeper which returns an object of type TimeKeeper and has a single (unnamed) parameter which is a pointer to function returning type Timer (and taking no input). (See Function object#In C and C++)
REFERENCE: https://en.wikipedia.org/wiki/Most_vexing_parse
Now, if we specify that void
must be used when declaring a function with no variables, does this not remove (not hackishly, fundamentally remove!) the ambiguity? The line in question would then become the following, leaving no doubt that it is a function declaration:
int main() {
TimeKeeper time_keeper(Timer(void));
return time_keeper.get_time();
}
This goes all the way back to KnR, where this issue is discussed:
Since the specialized versions of getline and copy have no arguments, logic would suggest that their prototypes at the beginning of the file should be
getline()
andcopy()
. But for compatibility with older C programs the standard takes an empty list as an old-style declaration, and turns off all argument list checking; the wordvoid
must be used for an explicitly empty list. [Kernighan & Richie, the C programming language, 1988, Pgs 32-33]
and..
The 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 [ibid, Pg. 73]
Reference: is f(void) deprecated in modern C and C++
foo bar();
from a function namedbar
returning afoo
to a variable of typefoo
namedbar
that is default constructed. – Marinmarinavoid
arguments, while the definition specifies an integer argument. – Hartwellfoo bar{};
being a variable, and keepfoo bar();
as the function declaration it has always been. – Lunarfoo bar();
is not the most vexing parse (see the link in the question). It's a function declaration, nothing more. People often confuse it with object creation, but that's not a parsing issue. The most vexing parse is far more vexing. – Milksop