Dies ist eine Fortsetzung einer anderen Frage.
Die ursprüngliche Frage hatte andere Probleme, aber ich musste erkennen, dass die Hauptfrage (laut CLang) a war Neudefinition von time
als anderes Symbol während nur Hübsch Es wurden C++-Includes verwendet.
Hier also eine abgespeckte Version:
#include<iostream>
using std::cout;
using std::endl;
class time
{
public:
int h, min, sec;
};
const int full = 60;
void canonify(time& pre) // Error here (line 14)
{
pre.min += pre.sec / full;
pre.h += pre.min / full;
pre.sec %= full;
pre.min %= full;
}
int main()
{
time a; // and here (line 23)
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(a);
cout << a.h << ":" << a.min << ":" << a.sec << endl;
}
Natürlich ersetzen time
mit einem anderen Symbol oder mit struct time
reicht um das Problem zu beseitigen. Anders gesagt meine Frage ist nicht wie man den Code zum Laufen bringt, sondern nur ob wir Symbole aus der C-Bibliothek als sehen müssen reservierte Token in C++. Clang 11 (auf MSVC19) drosselt mit:
1>ess.cpp(14,15): error : must use 'class' tag to refer to type 'time' in this scope
1>...\ucrt\time.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
1>ess.cpp(23,5): error : must use 'class' tag to refer to type 'time' in this scope
1>...\ucrt\time.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
Die Frage ist also: Wo verbietet der C++-Standard die freie Verwendung von Symbolen aus der C-Standardbibliothek, wenn sie nicht explizit in einer Kompilierungseinheit enthalten sind?
Interessanterweise funktioniert derselbe Code (einmal übersetzt …) in C einwandfrei:
#include <stdio.h>
//
typedef struct
{
int h, min, sec;
}time;
//
const int full = 60;
//
void canonify(time* pre)
{
pre->min += pre->sec / full;
pre->h += pre->min / full;
pre->sec %= full;
pre->min %= full;
}
int main()
{
time a;
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(&a);
printf("%d:%d:%d\n", a.h, a.min, a.sec);
return 0;
}
stackoverflow.com/questions/37589226/… Das scheint mir ein Dupe zu sein, aber ich bin nicht zuversichtlich, meinen Dupe-Hammer zu benutzen.
– Bolov
20. Juli 2021 um 12:42 Uhr
Der globale Namensraum ist sehr mit Bezeichnern verschmutzt. Titus Winters nannte es den wilden Westen. Es ist Ihrem Code nicht untersagt, Symbole im globalen Namensraum aus der C-Standardbibliothek zu verwenden. Das Einschließen der C++-verpackten C-Header-Dateien ist nicht verpflichtet, die C-Symbole im globalen Namensraum bereitzustellen (aber die meisten von ihnen tun dies – die meisten, aber nicht alle), unabhängig davon, ob sie es sind reserviert.
– Eljay
20. Juli 2021 um 12:46 Uhr
@bolov: Es ist tatsächlich das gleiche Problem. Aber die Sprache-Anwalt-Tag fragen Antworten mit präzisem Bezug auf die Norm. Aber ich muss zugeben, dass ich die andere Frage zuerst gefunden hätte, hätte ich diese nicht gestellt 😉
– Serge Ballesta
20. Juli 2021 um 12:56 Uhr
Zu Ihrer Information,
std::endl
ist hier völlig überflüssig. Rückkehr vonmain
wird spülenstd::cout
. Und im Allgemeinen besteht normalerweise keine Notwendigkeit, im Rahmen des Druckens eine Spülung zu erzwingen'\n'
– cout ist normalerweise bereits zeilengepuffert, wenn dies nützlich ist (dh wenn stdout ein TTY ist).– Peter Cordes
21. Juli 2021 um 0:55 Uhr
Der Grund, warum Ihre Übersetzung nach C funktioniert, ist der C-Standard verbietet Header der C-Standardbibliothek sollen sich gegenseitig einschließen (mit einem kleinen und dokumentierten Satz von Ausnahmen), während der C++-Standard erlaubt Header der C++-Standardbibliothek, die sich gegenseitig einschließen. So
iostream
kann Symbole aus exponieren und tut dies auchctime
aberstdio.h
, wenn es als C kompiliert wirdkann nicht Symbole ausstellentime.h
.– zol
21. Juli 2021 um 13:16 Uhr