Я заинтригован. Итак, время надеть защитные очки, и, поскольку у меня нет доступа к компилятору или флагам компиляции, мне нужно проявить изобретательность. Кроме того, потому что ничто в этом коде не имеет смысла, это не плохая идея, ставящая под сомнение каждое предположение.
Сначала давайте проверим фактический тип 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)
текст был заменен на input ( 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
use вместо этого», что действительно Хороший совет, но он еще больше сбивает с толку OP, так как любая попытка корректного чтения из stdin на этом сайте потерпит неудачу.
TLDR
gets(stdin)
является недействительным C ++. Это трюк, который использует этот конкретный сайт (по каким причинам я не могу понять). Если вы хотите продолжить отправку на сайт (я не одобряю и не одобряю его), вы должны использовать эту конструкцию, которая в противном случае не имела бы смысла, но помните, что она хрупкая. Практически любые модификации main
выложат ошибку. За пределами этого сайта используйте обычные методы чтения ввода.
stdin
в стандартной библиотеке естьFILE*
, и указатель на любой тип преобразуется вchar*
, который является типом аргументаgets()
. Тем не менее, вы никогда не должны писать такого рода код вне запутанного конкурса Си. Если ваш компилятор даже принимает его, добавьте больше флагов предупреждений, и, если вы пытаетесь исправить кодовую базу с этой конструкцией, превратите предупреждения в ошибки.