Я заинтригован. Итак, пришло время надеть защитные очки, и поскольку у меня нет доступа к компилятору или флагам компиляции, мне нужно проявить изобретательность. Кроме того, поскольку ничего в этом коде не имеет смысла, это не плохая идея, ставящая под сомнение каждое предположение.
Сначала давайте проверим фактический тип gets
. У меня есть маленькая хитрость для этого:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
И это выглядит ... нормально:
/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
Name<decltype(gets)> n;
^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
Name<decltype(gets)> n;
^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
^
1 warning and 1 error generated.
gets
помечен как устаревший и имеет подпись char *(char *)
. Но тогда как компиляция FirstFactorial(gets(stdin));
?
Давайте попробуем что-нибудь еще:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Что дает нам:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Наконец-то мы получаем что-то: decltype(8)
. Таким образом, весь текст gets(stdin)
был заменен на текстовый ввод (8
).
И все становится страннее. Ошибка компилятора продолжается:
/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
cout << FirstFactorial(gets(stdin));
^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;
Итак, теперь мы получаем ожидаемую ошибку для cout << FirstFactorial(gets(stdin));
Я проверил макрос и, поскольку #undef gets
, похоже, ничего не делает, похоже, что это не макрос.
Но
std::integral_constant<int, gets(stdin)> n;
Компилируется.
Но
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Нет с ожидаемой ошибкой в строке n2
.
И снова, почти любое изменение main
заставляет строку cout << FirstFactorial(gets(stdin));
выплевывать ожидаемую ошибку.
Более того, stdin
на самом деле кажется пустым.
Таким образом, я могу только заключить и предположить, что у них есть небольшая программа, которая анализирует исходный код и пытается (плохо) заменить gets(stdin)
входным значением тестового примера перед его фактической подачей в компилятор. Если кто-то имеет лучшую теорию или действительно знает, что он делает, пожалуйста, поделитесь!
Это, очевидно, очень плохая практика. Исследуя это, я обнаружил, что здесь есть, по крайней мере, вопрос ( пример ) об этом, и потому что люди не имеют представления о том, что существует сайт, который делает это, их ответ «не используйте gets
» используйте ... вместо этого ", который действительно является хорошим советом, но только больше сбивает с толку OP, так как любая попытка корректного чтения из stdin потерпит неудачу на этом сайте.
TLDR
gets(stdin)
является недействительным C ++. Это трюк, который использует этот конкретный сайт (по каким причинам я не могу понять). Если вы хотите продолжить отправку на сайт (я не одобряю и не одобряю его), вы должны использовать эту конструкцию, которая в противном случае не имела бы смысла, но помните, что она хрупкая. Почти любые изменения в main
приведут к ошибке. За пределами этого сайта используйте обычные методы чтения ввода.