Является ли наиболее Vexing Parse корневым в двусмысленности относительно того, использовать или не использовать void
как параметр объявления функции, который не принимает аргументов?
В качестве примера следующий код компилируется без ошибок и отлично работает на компиляторах g++ (v7.2.1) и Xcode (Apple LLVM версии 7.0.2 (clang-700.1.81)).
#include <iostream>
int asdf(void);
int asdf(int a) {
return a;
}
int main() {
std::cout << asdf(6) << std::endl; //-> 6
return 0;
}
Это полностью возвращается к стандарту ANSI-C и раньше, когда пустой список параметров указывал произвольное количество аргументов. Это преследует нас сегодня с обратной совместимостью в компиляторах, которые, похоже, немного смущены этой проблемой. Должно ли вышеуказанное не вызывать предупреждение, если не выдавать ошибку?
Здесь у меня было прозрение (или, возможно, сон!). Может ли быть, что The Most Vexing Parse коренится в двусмысленности в отношении использования void
в списке декларации пустой функции?
Другой пример: ссылка на следующий пример в Википедии:
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();
}
Линия
TimeKeeper time_keeper(Timer());
по-видимому, неоднозначно, поскольку его можно интерпретировать как
- определение переменной для переменной time_keeper класса TimeKeeper, инициализированное анонимным экземпляром класса Timer или
- объявление функции для функции time_keeper, которая возвращает объект типа TimeKeeper и имеет единственный (неназванный) параметр, который является указателем на функцию возвращаемого типа Timer (и без ввода). (См. Объект функции # В C и С++)
ССЫЛКА: https://en.wikipedia.org/wiki/Most_vexing_parse
Теперь, если мы укажем, что void
должен использоваться при объявлении функции без переменных, не устраняет ли это (не хаки, фундаментально удалить!) неоднозначность? Соответствующая строка затем станет следующей, не оставляя сомнений в том, что это объявление функции:
int main() {
TimeKeeper time_keeper(Timer(void));
return time_keeper.get_time();
}
Это все возвращается к KnR, где обсуждаются следующие вопросы:
Поскольку специализированные версии getline и copy не имеют аргументов, логика предполагает, что их прототипы в начале файла должен быть
getline()
иcopy()
. Но для совместимости с более старые программы C, стандарт принимает пустой список как старомодный объявление и отключает проверку списка всех аргументов; словоvoid
должен использоваться для явно пустого списка. [Керниган и Ричи, язык программирования C, 1988, стр. 32-33]
и..
Особый смысл списка пустых аргументов более старые C-программы для компиляции с новыми компиляторами. Но это плохая идея использовать его с новыми программами. Если функция принимает аргументы, объявляйте их; если он не принимает аргументов, используйте void [ibid, Pg. 73]