I was testing some code and I found out that I didn't need to put "#include <string>" in order to initialize a variable with a string and output it.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
#include <vector>
#include <memory>
int main() {
auto list = {1,2,3,4,5};
auto name{"The value is: "};
auto v = std::make_unique<std::vector<int>>(list);
for (auto x: *v)
std::cout << name << x << '\n';
}
The output is:
1 2 3 4 5
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
How is this possible without having the "#include <string>"?
Is this code ok or we should always use "#include <string>" in our code?
How is this possible without having the #include <string>?
The implementation is allowed to include the string header, or parts of it, at its whim. This is non-portable -- in other words, it is not required to compile. Best practice is to (directly) include the facilities that you need.
Can we be really sure in this example the type of “name” is std::string?
Bjarne Stroustrup, The C++ Programming Language, 4° edition, 6.3.5 Initialization
There is no advantage to using {} initialization, and one trap, when using auto to get the type determined by the initializer. The trap is that if the initializer is a {}-list, we may not want its type deduced (§6.3.6.2). For example:
1 2
auto z1 {99}; // z1 is an initializer_list<int>
auto z2 = 99; // z2 is an int
So prefer = when using auto.
(The following chapter 6.3.6.2 is entirely about this)
In my opinion, the only thing we can say is “name” is something std::cout has been instructed to manage.
Am I wrong?
#include <iostream>
#include <type_traits>
#include <cstring>
int main() {
// alias for 'lvalue reference to array of 15 const char'
using lvalue_ref_to_array = std::add_lvalue_reference< constchar[15] >::type ;
// type of name is deduced using the rules for template argument deduction for a function call
// where the parameter is passed by value.
// the type of the expression "The value is: " is 'array of 15 const char'
// ergo deduced type is 'pointer to const char'
auto name = "The value is: ";
static_assert( std::is_same< decltype(name), constchar* >::value,
"type of name should be 'pointer to const char'" ) ;
std::cout << sizeof(name) << '\n' ; // sizeof( const char*)
// type of name2 is deduced using the deduction rules for decltype
// the type of the expression "The value is: " is 'array of 15 const char'
// and its value category is lvalue.
// ergo, deduced type is 'lvalue reference to array of 15 const char'
decltype(auto) name2 = "The value is: ";
static_assert( std::is_same< decltype(name2), lvalue_ref_to_array >::value,
"type of name2 should be 'reference to array of 15 const char'" ) ;
std::cout << sizeof(name2) << '\n' ; // sizeof( const char[15] ) ie. 15
// type of name3 is deduced using the rules for template argument deduction for a function call
// where the parameter is passed by lvalue reference.
// the type of the expression "The value is: " is 'array of 15 const char'
// ergo, deduced type is 'lvalue reference to array of 15 const char'
auto& name3 = "The value is: ";
static_assert( std::is_same< decltype(name3), lvalue_ref_to_array >::value,
"type of name3 should be 'reference to array of 15 const char'" ) ;
std::cout << sizeof(name3) << '\n' ; // sizeof( const char[15] ) ie. 15
// type of name4 is deduced using the rules for template argument deduction for a function call
// where the parameter is passed by forwarding reference.
// the type of the expression "The value is: " is 'array of 15 const char'
// and its value category is lvalue.
// ergo, deduced type is 'lvalue reference to array of 15 const char'
auto&& name4 = "The value is: ";
static_assert( std::is_same< decltype(name4), lvalue_ref_to_array >::value,
"type of name4 should be 'reference to array of 15 const char'" ) ;
std::cout << sizeof(name4) << '\n' ; // sizeof( const char[15] ) ie. 15
}
So in case it's not entirely clear, my response is (partially) wrong, since I missed that that std::string is never used in @Rodev's code. OP's code is portable.