std::size_t is defined in any of:
<cstddef> <cstdio> <cstdlib> <cstring> <ctime> <cwchar>
Which is considered 'kosher' for getting just std::size_t?
Since this is part of the C library I think the C standard specified header is the right one: stddef.h, i.e. cstddef.
From C11:
7.19 Common definitions
The header defines the following macros and declares the following types. Some are also defined in other headers, as noted in their respective subclauses.
[...]
size_t which is the unsigned integer type of the result of the
sizeof operator;
This is after all a C++ question so I think a quote from the C++ standard is more appropriate:
18.2 Types
Table 30 describes the header <cstddef>.
Types: ptrdiff_t size_t max_align_t nullptr_t
Related
So I know any header from the C Compatability Headers:
Places in the global namespace each name that the corresponding cxxx header would have placed in the std namespace
I also know that these C headers were deprecated as of c++17, in favor of their compatibility "cxxx" counterparts.
Now, I believe that size_t is defined exclusively by the Standard Defines Header. So I presume this technically means that the definition of size_t in the global namespace has been deprecated?
I've been using it for years as just size_t and I'd just like a confirmation before I move to using std::size_t.
I presume this technically means that the definition of size_t in the global namespace has been deprecated?
Yes... but.
The Standard only mandates that std::size_t must be defined1 by <cstddef>, it does not disallow an implementation to define ::size_t2, but if the implementation does, the two definitions must match3.
As a conclusion, you should use std::size_t and should neither rely on ::size_t to be defined nor define it.
The following are UB:
// DON'T
using size_t = std::size_t; // UB
using size_t = decltype(sizeof 1); // UB
1) [cstddef.syn]
namespace std {
using ptrdiff_t = see below;
using size_t = see below;
using max_align_t = see below;
using nullptr_t = decltype(nullptr);
[...]
The contents and meaning of the header <cstddef> are the same as the C standard library header <stddef.h>, except that it does not declare the type wchar_t, that it also declares the type byte and its associated operations ([support.types.byteops]), and as noted in [support.types.nullptr] and [support.types.layout].
2)[extern.types]/1
For each type T from the C standard library (These types are [...] size_t,[...].), the types ::T and std::T are reserved to the implementation[.]
3)[extern.types]/1
[...] when defined, ::T shall be identical to std::T.
C-style header names like <stddef.h> are deprecated. However, C++-style headers like <cstddef> are allowed to declare their names in global namespace and then redeclare the same names in namespace std through using-declarations (http://eel.is/c++draft/organization#headers-4). This approach to declaring standard names is not deprecated. And many implementations do exactly that, for which reason it is not unusual to see name size_t accessible as a name from global namespace. But this is not guaranteed. So, in portable C++ code that includes <cstddef> you should use std::size_t and never rely on ::size_t's availability.
The standard says [expr.sizeof]:
The result of sizeof and sizeof... is a constant of type std::size_t. [ Note: std::size_t is defined in the standard header <cstddef> ([cstddef.syn], [support.types.layout]). — end note ]
Where is size_t Defined?
::size_t is guaranteed to be defined in <stddef.h> and few other C standard library headers that are inherited by c++. It may be defined by the implementation whether anything is included or not, since it is reserved, but relying on such non guaranteed definition would not be wise.
So I presume this technically means that the definition of size_t in the global namespace has been deprecated?
Indeed. More precisely, all standard headers that are guaranteed to define ::size_t are now deprecated in C++17. Same applies to all other non-macro C library names such as ::FILE.
Is it possible to remove standard features from C++
//Undefine some function from the standard like classes
class someclass
{
someclass(){
//Whatever
}
};
then get the error
"class undeclared identifier"
Not that I recommend it but you can use pre-processor macros to undefine anything you want.
If you compile the program below, you will get lots of errors.
#define vector
#include <vector>
int main()
{
vector<int> a;
}
You don't need the #define vector in the file. You can define it in the command used to invoke the compiler.
Note that using the above trick makes your program subject to undefined behavior:
From the C++11 Standard:
17.6.4.3 Reserved names
...
2 If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.
17.6.4.3.1 Macro names [macro.names]
1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
2 A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table [tab:identifiers.special], or to the attribute-tokens described in [dcl.attr].
When I'm switching the compiler version from gcc 4.6 to gcc 4.8 I get the following error
error: call of overloaded 'isnan(double)' is ambiguous.
This is because in c++11 there are differend function declarations:
C: int isnan(double)
C++11: bool isnan(double)
from cpluplus:
In C, this is implemented as a macro that returns an int value. The type of x shall be float, double or long double.
In C++, it is implemented with function overloads for each floating-point type, each returning a bool value.
How can I fix this?
Although you can mitigate this problem by not saying using namespace std; everywhere, you can avoid it by being explicit about using std::isnan:
#include <cmath>
#include <iostream>
int main()
{
double x = ....;
std::cout << std::boolalpha;
std::cout << std::isnan(x) << std::endl;
}
In C++11 there should not be ambiguity between the C and C++ isnan function. It works as expected, even with using namespace std.
Please check that you are not doing both #include <math.h> and #include <cmath>. Only include cmath.
Alternatively, perhaps you somewhere have in your project a user-defined isnan(double) function, or some header includes "math.h".
Also please note, that if one wants to write generic code, it is incorrect to use the 'std::' prefix on the math functions as it breaks the argument dependent lookup (ADL). (Because the C++ standard does not allow injecting functions in the std:: namespace)
The correct use for isnan in generic code is using std::isnan; then use just isnan on the variables. Otherwise your code with user defined floating point types such as for arbitrary precision, automatic differentiation and such wont work. The root of this inconsistency is that the built in types such as double do not reside in the namespace std but the functions that operate on them do.
I was playing with ptrdiff_t and reading the C++11 standard when I came across this "issue". First, the facts:
The type ptrdiff_t (just an example) is pulled from the Standard C library header <stddef.h> into <cstddef> (§18.2/2). Section 17.6.1.2 tells us that declarations pulled from the C standard library will be within the std namespace:
In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is
unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
As it also says, the declarations may have been declared in global namespace first and then injected into std. So it would make sense, for my implementation, that the following compiles just fine:
#include <cstddef>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
My implementation (gcc 4.6.3) must have declared ptrdiff_t in the global namespace and then injected it into std. However, if I compile the following code, I get an error (notice the <iostream> include):
#include <iostream>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:6:3: error: ‘ptrdiff_t’ was not declared in this scope
main.cpp:6:3: note: suggested alternatives:
/usr/include/c++/4.6/i686-linux-gnu/./bits/c++config.h:156:28: note: ‘std::ptrdiff_t’
So, since std::ptrdiff_t is available, <iostream> must be including <cstddef> in some way (although it's not required to). But why is the global version not also available as it
was before? Can I not expect this injection to be consistent even when it's actually the same header? This seems like odd behaviour. Whether the injection occurs may be unspecified, but it should at least be either one way or the other, not both, right?
Do not rely on one header including another, if you want something declared/defined in a specific header then you must include it.
For the example you gave, with g++ there are actually two definitions of ptrdiff_t (and size_t for that matter). The first, in namespace std, that comes from <bits/c++config.h>. And the one in the global namespace from <stddef.h> (and so <cstddef>).
The problem is that you did not using the correct header. You should do
#include <cstddef>
instead. However you use
#include<iostream>
And that has a definition of "std::ptrdiff_t" in it indirectly. However, the global "::ptrdiff_t" is not defined in "iostream" and "iostream" did not include "cstddef" as you thought. Instead, "iostream" does include "bits/c++config.h". The actual "std::ptrdiff_t" is defined in that file.
If you look at the content of the file "cstddef" you will find that is is only two "useful" lines there
BTW, the above discussion is for GCC 4.6 and GCC 4.7. For GCC 4.4, "iostream" indrectly include "cstddef" therefore ptrdiff_t will be available in both namespaces (std and global).
#include
#include
The latter line brings in the global "::ptrdiff_t" and the former defines the std namespace one.
Is this code standard conforming?
#include <stdio.h>
#include <cstdio>
int main() {
FILE *f1 = 0;
std::FILE *f2 = f1;
}
Explanation: The standard says [headers]:
[...] the contents of each header cname shall be the same as that of the corresponding header name.h [...] as if by inclusion. In the C++ standard library, however, the declarations [...] are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
So in case they aren't injected by explicit using-declaration, may they be different type? I don't think the "as if by inclusion" phrase is conclusive since the other half of the text clearly contradicts this requirement, requiring the names are within the std namespace.
Yes, that's standard conforming: FILE* is declared in stdio.h, std::FILE* in cstdio, and the two are the same because of the paragraph you cited.
(The only thing that's unspecified is whether, if you only include <cstdio>, you also have the same FILE* in the global namespace or not.)
Update: I believe that the types are actually the same on the nose, and that each type is declared only once and then injected in to the other namespace via a using declaration. The only thing that's unspecified is which one comes first. The corresponding opposite standard quote is D.5(2):
Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
Basically, that means that two implementations are possible:
"C came first":
// foo.h
struct Gizmo { /* ... */ };
// cfoo
#include "foo.h"
namespace std { using ::Gizmo; }
"C++ with C-compatibility:
// cfoo
namespace std
{
struct Gizmo { /* ... */ };
}
// foo.h
#include <cfoo>
using std::Gizmo;
I don't believe that paragraph says that they have to be identical. It is just a revision of the original (C++98) paragraph which said:
Every C header, each of which has a name of the form name.h behaves as if each name placed in the Standard library namespace by the corresponding cname header is also placed within the namespace scope of namespace std and is followed by an explicit using-declaration (7.3.3)
This was between hard and impossible to follow, because it conflicted with the existing real C headers on most systems. So, in C++11 the text was changed to the one you quote. It allows implementations to it the other way round, like they in practice have done all along - use existing system provided C headers and import the names to namespace std.
However, there is another paragraph saying that whichever way the implementation does this, the names in the headers must mean the same thing:
For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T. ([extern.types], 17.6.4.3.4)
Yes, they can be different types. Use the C++ types; the C headers are only there for compatibility.
Consider if as the comment to the answer above suggests, the C++ header were implemented as namespace std { #include "stdio.h" }; then ::FILE and std::FILE would represent different types.