Estou intrigado. Portanto, é hora de colocar os óculos de investigação e, como não tenho acesso aos sinalizadores de compilação ou compilação, preciso ser criativo. Também porque nada sobre esse código faz sentido, não é uma má idéia questionar todas as suposições.
Primeiro, vamos verificar o tipo real de gets
. Eu tenho um pequeno truque para isso:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
E isso parece ... normal:
/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
está marcado como descontinuado e tem a assinatura char *(char *)
. Mas então como está FirstFactorial(gets(stdin));
compilando?
Vamos tentar outra coisa:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
O que nos dá:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Finalmente estamos começando algo: decltype(8)
. Portanto, o todo gets(stdin)
foi substituído textualmente pela entrada ( 8
).
E as coisas ficam mais estranhas. O erro do compilador continua:
/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__;
Então agora obtemos o erro esperado para cout << FirstFactorial(gets(stdin));
Eu verifiquei uma macro e, como #undef gets
parece não fazer nada, parece que não é uma macro.
Mas
std::integral_constant<int, gets(stdin)> n;
Compila.
Mas
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Não com o erro esperado na n2
linha.
E, novamente, quase qualquer modificação para main
fazer a linha cout << FirstFactorial(gets(stdin));
cuspir o erro esperado.
Além disso, o stdin
fato parece estar vazio.
Portanto, só posso concluir e especular que eles têm um pequeno programa que analisa a fonte e tenta (mal) substituir gets(stdin)
pelo valor de entrada do caso de teste antes de realmente inseri-lo no compilador. Se alguém tiver uma teoria melhor ou realmente souber o que está fazendo, compartilhe!
Obviamente, essa é uma prática muito ruim. Ao pesquisar isso, descobri que há pelo menos uma pergunta aqui ( exemplo ) sobre isso e porque as pessoas não têm idéia de que existe um site por aí que faça isso, sua resposta é "não use o gets
uso ... em vez", o que é realmente um bom conselho, mas apenas confunde mais o OP, pois qualquer tentativa de leitura válida da stdin falhará neste site.
TLDR
gets(stdin)
é C ++ inválido. É um truque que esse site em particular usa (por quais razões eu não consigo descobrir). Se você deseja continuar enviando no site (eu não estou endossando nem endossando), você deve usar essa construção que de outra forma não faria sentido, mas esteja ciente de que é quebradiça. Quase todas as modificações main
causam erros. Fora deste site, use métodos normais de leitura de entradas.
stdin
na biblioteca padrão háFILE*
ae um ponteiro para qualquer tipo é convertido emchar*
, que é o tipo do argumento degets()
. No entanto, você nunca deve nunca escrever esse tipo de código fora de um concurso ofuscado em C. Se o seu compilador o aceitar, adicione mais sinalizadores de aviso e, se você estiver tentando corrigir uma base de código com essa construção, transforme os avisos em erros.