When should one include headers for built-in types?
<new>
for new
(seems for sophisticated overloadings it is really needed); it can be just used.<typeinfo>
for std::type_info
; it can be just acquired by using typeid
operator<initializer_list>
for std::initizlizer_list
; it is just result of auto l = {1, 2, 3};
or temporary in for (int i : {1, 2, 3}) {}
<cstddef>
/<cstdio>
/<cstring>
/<ctime>
for std::size_t
; it can be given as result of operator sizeof val
or sizeof(Type)
<cstddef>
for std::nullptr_t
; decltype(nullptr)
<cstddef>
for std::ptrdiff_t
; decltype(std::declval<int *>() - std::declval<int *>())
<tuple>
for some functionality of structured bindingsAre there cases when inclusion of corresponding headers is mandatory?
Strictly speaking, not all of your examples behave as you seem to expect. For instance
[expr.typeid]
6 If the header
<typeinfo>
is not included prior to a use oftypeid
, the program is ill-formed.[dcl.init.list]
2 ... The template
std::initializer_list
is not predefined; if the header<initializer_list>
is not included prior to a use ofstd::initializer_list
— even an implicit use in which the type is not named — the program is ill-formed.
So there's two examples right off the bat. And sure, you can get by without including some headers, for instance
using size_t = decltype(sizeof(0));
using nullptr_t = decltype(nullptr);
But in general, the way to guarantee with complete certainty that we get well-defined results, is to include the proper header for standard types.