-4

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;
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • 3
    Because there's no direct conversion between `double` and `std::string` perhaps? Can you elaborate what else you would expect please? – πάντα ῥεῖ Sep 20 '20 at 15:59
  • 1
    It's like asking why the presence of something like `int foo(std::string s) {return s.size();}` doesn't make `is_convertible_v` return `true`. – HolyBlackCat Sep 20 '20 at 16:04
  • @JesperJuhl I think my question is very clear. `std::string` took a `double` and turned it into a string. `std::is_convertible_v` just told me that's not possible. – Dimitrije Kostic Sep 20 '20 at 16:04
  • 3
    @DimitrijeKostic: "* std::string took a double and turned it into a string.*" No; ***`std::to_string`*** did that. It's not `std::string`. – Nicol Bolas Sep 20 '20 at 16:08
  • @NicolBolas Whoops, I meant to say `std::to_string` in my comment. – Dimitrije Kostic Sep 20 '20 at 16:09
  • @DimitrijeKostic: I guess the issue at hand is why you think that a random function should affect the implicit convertibility of two types? That is, why do you believe that the existence of `to_string` should affect the answer to the question of convertibility? What's missing from your question is why you think that this behavior is wrong, confusing, surprising, or otherwise questionable. – Nicol Bolas Sep 20 '20 at 16:11
  • @NicolBolas Because I didn't realize implicit convertibility was the underlying issue? Your answer below explains that pretty well, thanks. – Dimitrije Kostic Sep 20 '20 at 16:18

3 Answers3

9

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.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
4

std::is_convertible_v<double,std::string> being false means you can't do std::string(3.141592) (or more precisely double is not implicitly convertible to std::string), it has nothing to do with std::to_string.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
1

Because

std::string test() { return std::declval<double>(); }

is not well-formed code, as double cannot be converted implicitly, which is part of definition what std::is_convertible checks.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42