Search code examples
c++type-conversionstdstring

Why std::string seem to do something that std::is_convertible says isn't possible?


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;
}

Solution

  • 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.