Why does std::to_string
allow you to convert a double
to std::string
when std::is_convertible_v<double,std::string>
is false
? For example:
#include<iostream>
#include<type_traits>
#include<string>
int main()
{
std::cout << "If double is "
<< (std::is_convertible_v<double,std::string> ? "" : "not ")
<< "convertible to std::string then why is it possible to do this? "
<< std::to_string(3.141592) << std::endl;
return 0;
}
is_convertible
is asking a very specific question about the language relationship between two types: can the source type undergo implicit conversion to the destination type? And std::string
as a type has no implicit conversion into double
, so the answer is no.
std::to_string
is just a regular old function. It does not create any relationship between std::string
as a type and double
. Yes, it semantically converts a double
into a string
, but that is not an implicit conversion by the rules of the C++ language. As far as C++ is concerned, it's just a function.
C++ does not have a way to ask the question, "is there some function, somewhere, that can semantically convert an object of type X
to an object of type Y
?" And if that's the question you're trying to answer, there isn't really a functional way to get an answer.
It's important to note that the concept of implicit conversion is very special. Implicit conversions get to happen automatically in a lot of places. So if a type is implicitly convertible to another type, then that has a very strong meaning. If a string is implicitly convertible to a double, then that logically means that any function which takes a double also could be given a string.
Many languages consider this legitimate (though these languages usually are just using duck typing, so they don't typically have the concept of "a function which takes a double," merely "a function with takes a value"); C++ is not one of them. If you want to perform string-to-double conversion, C++ makes you spell it out.
Similarly, implicit conversion from one type to another is considered to be an intrinsic property of the types in question. That is, to create a user-defined conversion from X
to Y
, either X
or Y
must have a member function which defines this conversion. No third party code can create an implicit conversion between two types.