Reputation: 780
I am learning C++ and have found the following code in C++ primer:
int main() {
string s("some string");
for(decltype(s.size()) index = 0; index != s.size() && !isspace(s[index]); ++index)
s[index] = toupper(s[index]);
cout << s;
}
I understand the code capitalized the first word in the string and the output is
SOME string
What I am curious is that why do you need to use decltype(s.size())
to declare the type for index. If I change it to int index =0
, the code still compile and run with no problem. It seems easier for me to use int
. I think I am missing some import concept here, any feedback will be really helpful. Thanks!
Upvotes: 9
Views: 1709
Reputation: 780
Well, one place where decltype would be more useful would be:
template<class T1, class T2>
auto mul(T1 a, T2 b) -> decltype(a*b){
return a*b;
}
This template will allow you to multiply two things together, possibly of different types, and will return something of the correct type of the result of multiplying the two together. A hypothetical example might be multiplying two matricies together that results in some intermediate type class that defers the actual calculation until much later.
Upvotes: 2
Reputation: 11
The reason is that
the type of s.size()
member function of string class is string::size_type
which is unsigned and can
hold any length of string.
In this code index
is a variable that increase as the loop runs and it will increase
until its value becomes equal to s.size()-1
.
The length of string can be of any size.So we can't use int
for longer strings because it
can hold value of only specific range.So if string is longer in size index
can hold the value
of any size without showing any error.
Upvotes: 1
Reputation: 20386
You're not required to use decltype(s.size())
to declare the type, but declaring it as int
isn't necessarily a good idea. Or at least it's not a good habit to get into.
decltype(s.size())
literally means "this type should be the same as whatever std::string
uses to store the length of the string". In most C++ implementations, this is size_t
, which will either be an unsigned 64-bit integer (in most cases) or an unsigned 32-bit integer. In either situation, int
(which is signed and is probably not going to be 64-bits) is not going to represent the entire possible range of sizes for std::string
objects, which could, in exotic situations, be greater than 2.1 billion characters. In those situations, if you defined the type as int
, you'd run the risk of undefined behavior.
Note that in my code, I often just write for(size_t index = 0; index < string.size(); index++)
, because that's simpler. But if you want to guarantee that the code will behave on all platforms, for(decltype(string.size()) index = 0; index < string.size(); index++)
is the safest version of the code.
Upvotes: 8
Reputation: 206557
When do you require to use decltype in C++
I can think of the following.
When you want the compiler to deduce a type from:
You could have also used:
auto size = s.size();
for(decltype(size) index = 0; index != size && !isspace(s[index]); ++index)
s[index] = toupper(s[index]);
Upvotes: 1
Reputation: 180415
The reson they used decltype(s.size())
instead of int
is because using int
could cause a overflow which is undefined behavior. std::string::size()
returns a unsigned integer type that can store the largest size string you can make. If int
cannot hold that value and the string is that size then trying to run a int
to that value will never work
Before C++11 you would have had to use std::string::size_type
and if you changed the type then you would have to change the std::string
part. Now that we have C++11 and above we no longer need to do that. The compiler knows what the type of things are so if we use decltype(s.size())
we get the right type and if we ever change what s
is there is nothing in the for loop that needs to be changed. This is really nice from a maintainability stand point.
Upvotes: 3