Is <initializer_list> included in <iostream>? - c++

I know that the below code-block compiles
#include<initializer_list>
int main()
{
std::initializer_list<int> li = {1,2,3,4};
}
I can't understand why this also compiles
#include<iostream>
int main()
{
std::initializer_list<int> li = {1,2,3,4};
}
Is <initializer_list> included in <iostream>? According to this, it doesn't seem to be. Could this be a machine/compiler dependent thing?

Is <initializer_list> included in <iostream>?
It is not specified nor guaranteed to be.
But also, it is not guaranteed to not be included. Any standard header may include any other standard header, or system header. You should not rely on such transitive inclusion because another (version of the) standard library might not have such inclusion. Same generally applies to all third party headers as well. Only rely on a transitive inclusion if it is documented and guaranteed.

Related

Why does map not include out_of_range?

Consider the following code that doesn't compile:
#include <map>
//#include <stdexcept> // uncommenting this works
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
Why does std::map not include std::out_of_range, even if it uses it? (The .at() can throw a std::out_of_range).
When I also include <stdexcept> it compiles, and works fine.
Whether a standard header does include another header is an implementation detail unless explicitly specified.
With templates its a little more involved, but just to point you in some direction, consider this toy example:
// header: my_map.h
struct my_map {
int at(int);
};
Only in the source file the header for the exception has to be included:
// source: my_map.cpp
#include <stdexcept>
int my_map::at(int) {
throw std::out_of_range("bla");
}
std::map surely looks different but it may hide the exception from the header as well.
Is it also ok for a header to not include a decl for std::pair
The headers that are specified to be included via <map> are <compare> (since C++20) and <initializer_list> (since C++11). Nothing more.
<map> may include other headers and thats one of the "implementation details" mentioned in comments. The part of the standard that explicitly allows standard headers to include others is [todo.put reference here].
The simple rule of thumb that avoids such headace is: Include what you use.
but throwing std::out_of_range is not an "implementation detail" - it is part of the specification of std::map!
Consider that this code compiles with gcc 10.2:
#include <map>
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(...) {
return 1;
}
return 0;
}
The out_of_range exception is thrown and catched, and 1 is returned. We know what at may throw and catch(...) will catch it, yet no include is needed for the exception.
On the other hand, the same compiler rejects your example, but compiles it when we add a seemingly unrelated header:
#include <map>
#include <sstream> // why this?
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
However, this only works by coincidence. Apparently <sstream> does include <stdexcept> somewhere along the line. But this may change with compiler version or between differernt compilers.
The implementation of std::map doesn't have to be all in the header file. Yes this is a class template, but it is free to use any internal non-template components.
Consequently, the header file doesn't have to mention std::out_of_range (it may well be hidden inside one of those non-template components) and so doesn't have to have its definition visible anywhere, or behave as if it includes <stdexcept>. It is explicitly allowed to, but there is no implicit or explicit obligation in the standard for it to do so. So it might, or might not.
In fact g++-9 behaves as if <map> includes <stdexcept>, and g++-10 does not, and in both cases they are correct.
Why does std::map not include std::out_of_range
Assuming you are using GCC 10, GCC developers decided to optimize header dependencies in C++ Standard Library code. From Porting to GCC 10:
Header dependency changes
Some C++ Standard Library headers have been changed to no longer
include the <stdexcept> header. As such, C++ programs that used
components defined in <stdexcept> or <string> without explicitly
including the right headers will no longer compile.
Previously components such as std::runtime_error, std::string and
std::allocator were implicitly defined after including unrelated
headers such as <array> and <optional>. Correct code should include
the appropriate headers for the classes being used.
Also from GCC 10 Release Notes:
Reduced header dependencies, leading to faster compilation for some
code.

include STL header file inside a function C++14

tl;dr: Can I somehow make this code work in C++14 (GCC 6.3)?
int main(){
#include<vector>
std::vector<int> v{1,2,3};
return 0;
}
But code below works just fine!
#include <iostream>
using namespace std;
int main() {
#include<cstdio>
using namespace __gnu_cxx;
printf("Hello world\n.");
return 0;
}
Using C++14 (gcc-6.3) code doesn't compile with error message being
error: 'namespace' definition is not allowed here
namespace std
^~~~~~~~~
Why I want to do this?
I don't have access outside of the function where I am allowed to code. I can't #include in global area.
UPD: Changing to cstdlib also works problem is not exclusion by header guard (according to me) but namespace problem. Because C++ header files have namespace std, while c header files doesn't. I wanted to ask whether there is some tweak for namespace issue?
Can I somehow make this code work
No. Standard headers (and most library headers in general) must be included in the global namespace scope.
But code below works just fine!
But it's not guaranteed to work. It just happened to work, probably because <iostream> had already included <cstdio> and so your own inclusion was removed by header guards.

C++ --- Shouldn't these mathematical functions/constants be undefined?

I would not expect the following code that prints the value of sin(pi/2) to work, without the inclusion of an additional header:
#include <iostream>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
and, as expected, upon compilation I get an error reading ‘sin’ was not declared in this scope and a similar error for the use of M_PI.
However, I am confused by the fact that if I include seemingly any boost library header, take just for example the lexical_cast.hpp, and instead run
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
then the code works and it prints 1.
Why should including this boost header, which contains no definition of M_PI or sin(), allow this constant and function to be defined? Shouldn't I need to include a header, like math.h that includes these things for this to work?
Yes, it should work that way.
The boost headers you tried all have implicit dependencies (pow(), modf(), fmod(), log() etc).
This is a common thing in the C++ compilation model. Nothing to be alarmed by.
Guideline: always explicitly include the headers you directly depend on. And only those.
This prevents portability issues on platforms where the library header dependency tree differs e.g. <algorithms> and <numeric> aren't implicitly included with some other standard library headers (e.g. MSVC)

math.h macro collisions

Macro DOMAIN in math.h collides with enums and possibly other types. I don't know what to make of it.
#include <algorithm>
enum Type { DOMAIN };
int main(){
Type t = Type::DOMAIN;
return 0;
}
Compile with flag -std=c++11. The C99 version of this code compiles perfectly fine though:
#include <algorithm>
enum Type { DOMAIN };
int main(){
Type t = DOMAIN;
return 0;
}
I checked the source code and the library is to blame. algorithm includes stl_algo.h, in which there is ifdef:
#if __cplusplus >= 201103L
#include <random> // for std::uniform_int_distribution
#include <functional> // for std::bind
#endif
The following code compiles fine on c++11 compiler:
#include <random>
#include <iostream>
int main(){
std::cout << DOMAIN << std::endl;
return 0;
}
Is it a feature or a bug?
EDIT* dirty fix:
#ifdef DOMAIN
#undef DOMAIN
#endif
It's a bug (or a "wart" if you want to be generous).
All the rest of this answer refers only to GCC and the Gnu standard C library headers. The man page references are to a linux system (but I've added links to man7.org).
The DOMAIN macro comes from math.h's System V support. (See man matherr.) System V support is normally enabled by defining the _SVID_SOURCE feature-test macro (see man feature_test_macros), but it is enabled along with a raft of other extensions if _GNU_SOURCE is defined, or by default if no feature test macros are defined.
gcc predefines _GNU_SOURCE for C programs if the --std option is omitted or set to gnu##. The various --std=c## options cause __STRICT_ANSI__ to be defined. Consequently, compiling C code with some explicit C standard will suppress the System V extensions. That needs to be done because the System V extensions are not standards-compatible, not even with Posix, because they pollute the global namespace. (DOMAIN is just one example of this pollution.)
However, g++ defines _GNU_SOURCE even if --std=c++## is specified, and consequently the System V extensions will sneak in. (Thanks to #dyp for the link to this libstdc++ FAQ entry. and this long and inconclusive discussion from 2001 on the GCC mailing list)
An ugly workaround is to set up the features yourself, and then undefine __USE_SVID:
#include <features.h>
#undef __USE_SVID
#include <random>
#include <iostream>
int main(){
std::cout << DOMAIN << std::endl;
return 0;
}
(Live on coliru)
IMHO, this should not be necessary. But there it is.
§ 17.6.5.2 [res.on.headers] / 1 of N4140 says:
A C++ header may include other C++ headers. A C++ header shall provide the declarations and definitions that appear in its synopsis. A C++ header shown in its synopsis as including other C++ headers shall provide
the declarations and definitions that appear in the synopses of those other headers.
Therefore, it is valid for <algorithm> to #include <cmath> which injects the offending macro constant into your namespace.
Note, however, that your “quick and dirty fix” is disallowed by the standard (§ 17.6.4.3.1 [macro.names] / 1):
A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
You'll have to choose a name different from DOMAIN for your enum constant.

why should i include the header file <iostream> after using the namespace std?

Since the namespace std already has the c++ libraries that contain the function definitions(if i am right), then why do we include header files on top of it??. Since namespace std includes the c++ standard libraries, I don't see a reason to include the declarations of it separately.
When you do #include <iostream> it causes a set of classes and other things to be included in your source file. For iostream, and most of the standard library headers, they place these things in a namespace named std.
So the code for #include <iostream> looks something like this:
namespace std {
class cin { ... };
class cout { ... };
class cerr { ... };
class clog { ... };
...
}
So at this point, you could write a program that looks like:
#include <iostream>
int main() {
std::cout << "hello\n";
return 0;
}
Now, some people feel that std::cout is too verbose. So they do:
#include <iostream>
using namespace std;
int main() {
cout << "hello\n";
return 0;
}
Personally, I'd recommend against this, and if you really feel that std::cout is too verbose, then I'd suggest that you use a smaller using statement.
#include <iostream>
using std::cout;
int main() {
cout << "hello\n";
return 0;
}
If you're wondering why I would recommend against using namespace std, then I would forward you to the following two other posts on stackoverflow:
C++ Distance Function Keeps Returning -1
Why is "using namespace std" considered bad practice?
The compiler itself does not have the definitions of the things that are in any namespace (whether it is std or some other namespace). That is the role of source files and header files.
What using namespace std; tells the compiler is that "If you can't find some name in the current namespace, go look in the std namespace as well".
What #include <iostream> tells the compiler is that you want the contents of the header called iostream to be included in your sources. This will provide the compiler with code to do cin, cout and a lot of other related functionality. The content of this file is declared like namespace std { ... all the stuff goes here ... }.
The usage of namespace allows someone else, working in namespace math; to not have to worry about "Hmm, what do I do now, I need a counter for number of entrances, let's call it cin - but hang on, is that ever used anywhere?".
This may not be the greatest of examples, but in large projects, it gets increasingly hard to keep track of things and what names they have. And C++ is a language intended for large projects of millions of lines of code - and now it starts getting hard to remember if you've used a particular name or not. Namespaces make sure that you don't have to worry about it outside of a particular namespace.
(Oh, and in my code, I tend to not use using namespace std;, but write std::cout << "Hello, World!" << std::endl; - this helps to make it clear that the cout I'm using here is the std one, and not something else. This is particularly useful when you have several namespaces with similar things, like in my own compiler, where I have my compiler with it's functionality, the std namespace providing some things, and llvm compiler things - if I were to stick using namespace llvm; at the beginning of the code, it would be very hard to track whether Type* p = ...; is from LLVM or some part of my own code.)
...why do we include header files on top of it???
Yes, there is some big confusion here.
Namespaces
Namespaces are a method to categorize or group together, symbols such as function names.
Namespaces are design to prevent name conflicts between different software components, such as libraries.
Functions that are a part of the standard language, are grouped under the namespace std.
The C++ language provides statements to reduce the amount of typing when using namespaces. One of these is the using statement.
Header (include) Files
When you write a program, the compiler is not required to automatically include all the symbol definitions, such a function declarations. You need to tell it which functions you plan on using.
For example, I could write a program without using the sort or advance functions from the algorithm group. Therefore I would not include the header file algorithm.
The C++ language is designed to be "use what you need", in other words, we can create small programs by only including the functions we need.
Other Platforms
By the way, there are many other platforms out there than the one you are using.
Some platforms need to fit in small memory areas and may not have a keyboard or display (such as embedded controllers).
So remember, C++ was defined to support platforms from the small and constrained to the large and virtually unconstrained system.
Thus the requirement to "include only what you need" theme.
Summary
In summary, since the C++ languages doesn't automatically, magically, provide the definitions of the entire library, including the template library, you need to tell the compiler which groups of functions you want to use. This allows for quicker compilations since only the required header files are specified.
Note: Some shops and library supplies like to use the Monolith include system. This means that they have one include file that includes their entire library, whether you use one function or many. The windows.h is a classic example. One detriment is that when one header file is changed, everything needs to be rebuilt. With separated include files, only the components that include the changed header file need to be rebuilt.
Use of preprocessor directive #include is as old as c++ itself. And its not going away any sooner.In C++ namespace Doesn't import anything into your program, it just defines the scope of your particular header file's function.So, both are required. Click hereto understand why use namespace.
Your question is: namespace std has all the definitions of functions/classes of iostream library. So simply using using namespace std is enough to call or use cout or all other functionalities of iostream library. Why do we have to use line #include <iostream>? It seems redundant.
Roughly we can think that iostream library has two files: header and implementation/source file. These two files have a namespace called std. The header file only contains the declarations or forward declarations of classes or functions or variables that iostream library is going to use and these declarations or forward declarations are under the std namespace. The implementation file contains the actual implementations of the classes or functions or variables and these implementations are under the std namespace; this file is also called the source file.
So if you only use using namespace std without #include <iostream> in your main.cpp file compiler will search std namespace in your main.cpp file, but it is not here. You will get compiler error.
Now if you include this #include <iostream> line in your main.cpp, preprocessor will go iostream's header file and copy the std namespace along with its code into our main.cpp. And linker will link the precompiled(as iostream is a SLT so it comes with compiler with prebuilt) source/implementation file of iostream to your main.cpp. Now to use functions or variables of iostream that sit under std namespace in main.cpp we have to use scope resolution operator(::) to tell the compiler that cout, cin and other functionalities of iostream sit at std namespace. Thus we simply write like this: std::cin, and std::cout.
Now typing std:: seems redundant to some people so they tell the compiler by using this using namespace std "Hey compiler, if you don't find any variables/functions/classes in global/current namespace go look in the std namespace." Though this is not the best practice but that is another topic to discuss. Therefore your assumption that std namespace contains all the definitions of all SLT's functions/classes/variables of C++ is not correct in most cases, but std namespace only contains the declaration from STL is the correct assumption.
Here is a dummy implementation how iostream libray is added to our code files:
iostream.h:
// This is header file that only contains the
// functions declarations.
namespace std_dum
{
int add(int x, int y);
int mult(int x, int y);
}
iostream_dum.cpp:
// This is source file of iostream_dum.h header
// which contains the implementation of functions.
#include "iostream_dum.h"
namespace std_dum
{
int add(int x, int y)
{
return x + y;
}
int mult(int x, int y)
{
return x * y;
}
}
main.cpp :
#include <iostream>
#include "iostream_dum.h"
int main()
{
std::cout << std_dum::add(100, 200) << '\n';
std::cout << std_dum::mult(100, 200) << '\n';
return 0;
}
To see what happens to our main.cpp file after preprocessing run this command: g++ -E main.cpp iostream_dum.cpp.
Here is roughly our main.cpp looks like:
namespace std_dum
{
int add(int x, int y);
int mult(int x, int y);
}
int main()
{
std::cout << std_dum::add(100, 200) << '\n';
std::cout << std_dum::mult(100, 200) << '\n';
return 0;
}
namespace std_dum
{
int add(int x, int y)
{
return x + y;
}
int mult(int x, int y)
{
return x * y;
}
}
For the sake of clarity, I discarded all the codes that the preprocessor copied from #include <iostream>.
Now it should be pretty clear.