This is a follow-up to a different question.
The original question had other problems but I had to realize that the main one (according to CLang) was a redefinition of time
as a different symbol while only nice C++ includes were used.
So here is a stripped-down 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;
}
Of course, replacing time
with a different symbol or using struct time
is enough to get rid of the problem. Said differently my question is not how to make the code run, but only whether we have to see symbols from the C library as reserved tokens in C++.
Clang 11 (on MSVC19) chokes with:
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
So the question is: where does the C++ standard forbid freely using symbols from the C standard library when they are not explicitly included in a compilation unit?
Interestingly enough the same code (once translated...) works fine in C:
#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;
}
[extern.names]
3 Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
Note that this paragraph reserves the name itself. So aliasing time
in the global namespace violates this contract.