C++ "size_t" doesn't need "cstddef" header? - c++

I'm learning C++ with the book C++ Primer, and it says that "size_t" is defined in "cstddef" header, but in this exercise:
#include <iostream>
using namespace std;
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
cout << ar[a] << " ";
cout << endl;
return 0;
}
That doesn't have included the header, Visual Studio 2017 (and c++ shell) compiles the program without error.

size_t is really a grey area. std::size_t is the result type of sizeof, but sizeof is a built-in operator you can use without any #include at all. Consider this complete little program:
// no includes, no using namespace std
int main()
{
auto x = sizeof(int); // x is std::size_t
}
On top of that, Visual C++ has always behaved a bit strangely here. Even with settings like /permissive- /std:c++latest in the newest version of the compiler, it still allows the following illegal code:
// no includes, no using namespace std
int main()
{
size_t i = 0;
}
In fact, it would even allow this:
// no includes, no using namespace std
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
;
return 0;
}
Nevertheless, what others said about the indirect inclusion of headers is correct. To be precise, the C++ standard says the following about standard-library headers at §20.5.5.2:
A C++ header may include other C++ headers.
Which means that Visual C++ behaves correctly in your case anyway. Once you include <iostream>, the implementation is free to indirectly include one of the six standard C++ headers that define std::size_t, and your using namespace std; (which is evil) does the rest.
The C++ standard even guarantees some of such indirect inclusions, but this isn't one of them, so in order to make your code compatible with other compilers, you are strongly encouraged to include <cstddef> or one of the others that guarantee std::size_t.

Standard headers are allowed to include other standard headers. Since headers in different implementations have different dependencies, you should still try to explicitly include everything that you need. It's possible that your program wouldn't build on Linux's libstdc++ or macOS's libc++, for instance.

Standard header will usually include other standard headers, so in many cases you might get away with not including proper ones.
The problem is that such relations between headers are not in the standard e.g. depend on implementatation. If you don't include required headers, your code might work on one compiler, but might fail on another.
Usually if you know that something defined in header X uses type T in its definition, you might assume type T will be available after including X. For example <vector> uses std::size_t as part of std::vector definition, so it will usually include <cstddef>.
Sometimes forward declarations can be used to avoid including other standard headers. But this is only possible with classes and structures, not typedefs.
Some implementations, like GNU Libc for example, are more strict and try to avoid including standard headers internally. Others, like MSVC, are less strict. Code that works with GNU Libc will usually work with MSVC.
It is hard to verify that your code includes everything you need. There are tools that can help you find missing include's, but building your code with multiple compilers is usually the best way to find those issues.

Nope, std::size_t might be defined in multiple headers:
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstdlib>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
Also note, that <iostream> itself includes other headers.

Firstly, std::size_t is defined in a number of standard headers: <cstddef>, <cstdio>, <cstdlib>, <cstring>, <ctime>, and <cwchar>.
Without #includeing one of these, your code is not required to compile.
Practically, a lot of implementations of the standard library have various standard headers #include each other, in which case your code will compile. It is pretty common, but NOT guaranteed, for at least one of the headers that defines std::size_t (or even their C header equivalents like <stddef.h>) to be included by other headers in the C++ standard library.
More specifically, a lot of parts of the standard library work use dynamic memory allocation (standard containers, stream buffers, etc). An obvious - but not required - implementation choice is that they use size_t to represent sizes. For example, standard containers like std::vector have an associated size_type, and std::vector<any_type>::size_type can be, and often is, equivalent to std::size_t.
<iostream> (along with headers it automatically #includes) is not required to include a header that defines std::size_t, but - equally - nothing in the standard disallows it.
In the end it comes down to how cautious you want to be concerning portability. If <iostream> brings in a definition of std::size_t with your particular compiler, then your code will compile. It is possible (although unlikely in practice, not impossible) that a future release of your compiler will update the standard headers to change that. If you intend to port your code to another implementation (compiler and standard library) in future, there is a greater likelihood your code will need to be modified.
Practically, there is no harm by explicitly #includeing <cstddef> or any other header that defines std::size_t. That way, your code that uses std::size_t will compile, regardless of how other standard headers vary between implementations.

Related

Why does a header file work in Windows but not on Mac & Linux? (strrev)

I am exploring the work on cstring inside a C++ code. One of the functions that is commonly used is strrev().
But I found that this function is considered undefined on Mac & Linux, even if I included the header file <cstring> or <string.h>.
However, the function works fine on Windows.
(I am aware that I can define the function myself as the solution presented in here strrev not available on Linux)
This might be a very naive question, but aren't the definitions of header files supposed to be the same across different platforms? or does each platform have a different definition of the header file?
Another weird thing that is I did not find strrev() in the description of the <cstring> header file (cstring header file description), but if I don't include this header file on Windows I get an error and the error is resolved when I include it.
One of the functions that is commonly used is strrev().
Actually, other than in programming classwork, I can't think of any viable reason why strrev() would be useful. I don't think I've had a need for such a beast in my entire multi-decade career :-)
The reason it's not defined in some platforms is because it's not mandated by the C++ standard.
The reason why it's defined in some other implementations is because the standard dictates what must to be made available, not what mustn't. In other words, implementations are allowed to include it, they're just not required to include it.
An implementation can choose to include all sorts of wonderful extra stuff, provided it doesn't break any of the stuff mandated by the standard.
It's an implementation specific decision to include certain functions other than the standard ones.
However, in C++, you may use std::reverse from <algorithm> header to reverse the string.
Here's an example:
#include <iostream>
#include <algorithm>
int main()
{
char s[] = "Hello World!";
std::reverse( std::begin(s), std::end(s) );
for ( const auto& i : s )
{
std::cout << i;
}
return 0;
}
Output string:
!dlroW olleH
here is a link where you shall find the list of function & class that should be in the header according to the standard : http://www.cplusplus.com/reference/
About the question on the header itself, C++ standard does not propose one uniformed header, but the list of what is required.
And the definitions in the headers will even vary for the same compiler, from one target to another (32 or 64 bits, etc.. ). If you check the iostream header for GCC, for instance, it includes 3 files :
#include <bits/c++config.h>
#include <ostream>
#include <istream>
the header under the bits/ directory usually vary from one target to another, and you don't directly include it in your own application.

Why can I use size_t and std::size_t in MSVS without the traditional headers?

I am working with Visual Studio 2017 Community Edition. It allows me to use both size_t and std::size_t without the appropriate includes. It appears to work with most of the std library. I assume it is because parts of the library itself use it. For instance one example that I found led to this behave was with vector.
#include <vector>
#include <iostream>
int main()
{
size_t a = 42;
std::size_t b = 0;
std::cout << a << b;
std::cin.ignore();
}
Presumably this is because the size() function returns an std::size_t. Is this just a header dependency and I can avoid it with the proper include? That still doesn't explain why I can call it with the namespace scope.
(I'm not using using namespace std.)
This question implies that not all headers in the std library should have the definition.
Strictly speaking your code is illegal. The size_t type is required to be declared in the following headers:
<cstddef>
<cstdio>
<cstdlib>
<cstring>
<ctime>
<cwchar>
But also the standard allows standard headers to include other standard headers. So most likely the header <vector> in the standard library used by MSVC includes one of the headers above. This is allowed, but not mandated by the standard so this will work on your setup, but can fail to work on other standard library implementations, even on a future version of the same one you are using.
So in conclusion try to include all the headers required by the standard for all the definitions you are using.
IMHO this is a faulty behavior, but is the required price C++ pays for backward compatibility to the inclusion system that seemed a reasonable design many years ago. The limitations and drawbacks of this are well known today and so the committee is working on modules, which is a modern alternative to the current inclusion mechanism.
As to why you can use size_t without std:::
<cstddef> is required to declare std::size_t and may also optionally declare (or bring in the declaration of) size_t in the global scope.
<stddef.h> is a C backward compatible header and it declares size_t at the global scope.
So either <cstddef> declares size_t at a global level and is included by <vector> or <stddef.h> is included by <vector> - most likely indirectly via <cstddef>.
https://stackoverflow.com/a/283023/2805305

Compiling without (necessary?) #include

Consider the following code:
#include <iostream>
using namespace std;
int main () {
srand(time(0));
double dd [10];
for(int i=0;i!=10; ++i) dd[i]= rand()%5+0;
for(auto i:dd)
cout<<i<<' ';
cout<<endl;
exit(100);
}
Why is it compiling without the #include<ctime> and #include<cstdlib> for the calls to time(0) and exit(100)(which is absolutely useless there, I know)? Are they already included in iostream?
The C++ standard, section 17.6.5.2 [res.on.headers], says:
A C++ header may include other C++ headers.
Which means an implementation is free to include other headers when you include one of them. From an implementor's point of view, that's just quite practical, of course.
There are even headers which are guaranteed to include others. For example, <string> implies <initializer_list>.
As for <iostream>, it implies <ios> (which itself implies <iosfwd>), <streambuf>, <istream> and <ostream>. So there is no guarantee for <ctime> and <cstdlib>, and you should include them explicitly for better portability.
To find out which headers are guaranteed to include others, you can either have a look yourself in the standard or in a draft (see all the synopses starting in section 18), or just go to cppreference.com, for example http://en.cppreference.com/w/cpp/header/iostream for <iostream>. It's quite a reliable online C++ reference.
Or you just explicitly include every header you need. Which may be the best choice in the end.
Yes, iostream includes cstdlib (at least in your case; you should not rely on that dependency chain).
Your compiler might have an option to list the dependencies, e.g. for the GNU C compiler, you can use the -M flag to list all includes.

size_t on XCode

It seems on XCode I need to use std::size_t instead of just size_t on Visual C++. But this is a pain as I don't really want to have to #include <cstddef> and change every size_t to std::size_t in my code... in my Windows code size_t just works without including any additional files.
Is there a way to make my existing code work in XCode, (maybe through the .pch file?) or are GCC/MSVC++ fundamentally different in this regard and my code needs to use std::size_t in order to be cross-platform?
According to the C++03 standard, 17.4.1.2.4:
Except as noted in clauses 18 through 27, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity, (Clause 7), as appropriate, as if by inclusion. In the C++ Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std.
In other words, by choosing to use <cstddef> instead of <stddef.h>, you're specifically asking for the type size_t to be within the namespace std.
So, here are the choices:
Use <stddef.h> instead, so size_t is in the top-level namespace, as suggested by Jesse Good.
Use <cstddef> and use std::size_t.
Use <cstddef> and use a using declaration to pull size_t into the top-level namespace, as suggested by cnicutar.
Of course you could rely on the fact that one particular version of one compiler/library/platform lets you get away with it, or write different code for each platform, or wrap the whole thing up with autoconf, or write a code generator or sed-based preprocessor, or whatever… but why?
Perhaps saying this somewhere near the top ?
using std::size_t;
Use #include <stddef.h>.
So, what's the difference between #include <stddef.h> and #include <cstddef>?
<cstddef> is a C++ header and is guaranteed to define all symbols in the std namespace and also may define things in the global namespace.
<stddef.h>is a C header and is guaranteed to define all symbols in the global namespace and may also define things in the std namespace.
So, as you said on Visual Studio, size_t can be used because it injects size_t into the global namespace for you (possibly by already including "stddef.h"). If you want that to work on any compiler include stddef.h.
(However, as a pure C++ fan, I personally prefer std::size_t).

In what cases we need to include <cassert>?

In what cases should we include cassert?
In short, don't use it; use <assert.h>.
C++11 removed any formal guarantee of a "c...." header not polluting the global namespace.
It was never an in-practice guarantee, and now it's not even a formal guarantee.
Hence, with C++11 there is no longer any conceivable advantage in using the "c...." header variants, while there is the distinct and clear disadvantage that code that works well with one compiler and version of that compiler, may fail to compile with another compiler or version, due to e.g. name collisions or different overload selection in the global namespace.
SO, while cassert was pretty meaningless in C++03 (you can't put a macro in a namespace), it is totally meaningless -- even as a special case of a general scheme -- in C++11.
Addendum, Dec 22 2013:
The standard defines each C++ C header <X.h> header in terms of the <cX> header, which in turn is defined in terms of the corresponding C library header.
C++11 §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.”
C++11 §D.5/3 (non-normative example):
“The header <cstdlib> assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std.”
Stack Overflow user C.R.’s comment made me aware that some versions of g++, such as MinGW g++ 4.7.2, are quite non-standard with respect to the <X.h> headers, lacking the overloads of e.g. sin that the C++ standard requires:
I already knew that MinGW g++ 4.7.2 also entirely lacks functions such as swprintf, and that it has ditto shortcomings in the pure C++ library such as lacking C++11 std::to_string. However, the information about it lacking the C function overloads was new to me.
In practice the lacking overloads with g++ means
ignoring the g++ issue, or
avoiding using the missing g++ overloads,
e.g. using only double sin( double ), or
using the std namespace overloads
(one then needs to include <cmath> to guarantee their presence with g++).
In order to use the g++ std namespace overloads unqualified, one practical approach is to define headers wrappers for this compiler. I've used that approach to address g++ shortcomings wrt. to the printf family. For as David Wheeler once remarked, “All problems in computer science can be solved by another level of indirection”…
Then things can be arranged so that standard code that uses g++'s missing overloads, also compiles with g++. This adjusts the compiler to the standard, with a fixed amount of code.
Just like any other header file, you #include <cassert> when you use something declared in that header file, such as assert().
See an easily accessible reference
#include <iostream>
// uncomment to disable assert()
// #define NDEBUG
#include <cassert>
int main()
{
assert(2+2==4);
std::cout << "Execution continues past the first assert\n";
assert(2+2==5);
std::cout << "Execution continues past the second assert\n";
}
assert.h defines one macro function that can be used as a standard debugging tool.