Sono incuriosito. Quindi, è tempo di indossare gli occhiali di indagine e dato che non ho accesso al compilatore o ai flag di compilazione, devo essere inventivo. Anche perché nulla di questo codice ha senso non è una cattiva idea in ogni ipotesi.
Per prima cosa controlliamo il tipo effettivo di gets
. Ho un piccolo trucco per questo:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
E questo sembra ... normale:
/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
è contrassegnato come obsoleto e ha la firma char *(char *)
. Ma allora com'èFirstFactorial(gets(stdin));
compilando?
Proviamo qualcos'altro:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Che ci dà:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Finalmente stiamo ottenendo qualcosa: decltype(8)
. Quindi l'intero è gets(stdin)
stato sostituito testualmente con l'input (8
).
E le cose diventano più strane. L'errore del compilatore 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__;
Quindi ora otteniamo l'errore previsto per cout << FirstFactorial(gets(stdin));
Ho controllato per una macro e da allora #undef gets
sembra non fare nulla sembra che non sia una macro.
Ma
std::integral_constant<int, gets(stdin)> n;
Si compila.
Ma
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Non con l'errore previsto al n2
riga.
E ancora, quasi ogni modifica per main
rendere la lineacout << FirstFactorial(gets(stdin));
sputare l'errore previsto.
Inoltre il stdin
realtà sembra essere vuoto.
Quindi posso solo concludere e ipotizzare che abbiano un piccolo programma che analizza la fonte e cerca (male) di sostituire gets(stdin)
il valore di input del test case prima di inserirlo nel compilatore. Se qualcuno ha una teoria migliore o effettivamente sa cosa sta facendo, per favore condividi!
Questa è ovviamente una pessima pratica. Durante la ricerca di questo ho scoperto che c'è almeno una domanda qui ( esempio ) su questo e perché le persone non hanno idea che ci sia un sito là fuori che fa questo la loro risposta è "non usare gets
uso ... invece" che è davvero un buon consiglio, ma confonde solo di più l'OP poiché qualsiasi tentativo di lettura valida da stdin fallirà su questo sito.
TLDR
gets(stdin)
non è C ++ valido. È un espediente che questo particolare sito utilizza (per quali motivi non riesco a capire). Se vuoi continuare a inviare sul sito (non lo sto sostenendo né lo sto sostenendo) devi usare questo costrutto che altrimenti non avrebbe senso, ma tieni presente che è fragile. Quasi tutte le modifiche apportate main
genereranno un errore. Al di fuori di questo sito utilizzare i normali metodi di lettura dell'input.
stdin
nella libreria standard è unFILE*
, e un puntatore a qualsiasi tipo viene convertito inchar*
, che è il tipo dell'argomento digets()
. Tuttavia, non dovresti mai, mai, mai scrivere quel tipo di codice al di fuori di un contest offuscato C. Se il compilatore lo accetta, aggiungi altri flag di avviso e se stai cercando di correggere una base di codice che contiene quel costrutto, trasforma gli avvisi in errori.