Является ли наиболее Vexing Parse коренится в двусмысленности относительно того, следует ли использовать void
в качестве параметра объявления функции, которое не принимает аргументов?Указывает использование void в объявлении функции, которая не принимает аргументов, для параметра The Most Vexing Parse?
В качестве примера следующий код компилируется без ошибок и работает нормально, как для g ++ (v7.2.1), так и для Xcode (Apple LLVM version 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 класса TimeKe eper, инициализированный анонимным экземпляром класса Timer или
- объявление функции для функции time_keeper, которая возвращает объект типа TimeKeeper и имеет один (неименованный) параметр, который является указателем на функцию возвращаемого типа Таймер (и не принимает вход). (См объект Function # В C и 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
должно использоваться для явно пустого списка. [Керниган & Richie, язык программирования C, 1988, PGS 32-33]
и ..
Особое значение пустого списка аргументов предназначен для обеспечения старых программ C для скомпилировать с новыми компиляторами. Но это плохая идея для использования с новыми программами. Если функция принимает аргументы, объявите ; если он не принимает аргументов, используйте void [ibid, Pg. 73]
Ссылка: is f(void) deprecated in modern C and C++
«Должно ли вышеуказанное не вызывать предупреждение, если не выдавать ошибку?» Нет. Почему ты так думаешь? Этот код объявляет две функции, предоставляет определение для одного из них и вызывает его. –
Самый неприятный синтаксический разбор - как вы отделяете 'foo bar();' от функции с именем 'bar', возвращающей' foo' переменной переменной 'foo' с именем' bar', которая по умолчанию построена. – NathanOliver
@latedeveloper 2, из-за несоответствия аргумента между объявлением функции и определением; в частности, декларация указывает аргументы '' void'', в то время как определение указывает целочисленный аргумент. – kmiklas