为什么 std::string 似乎做了一些 std::is_convertible 说不可能的事情?

Dim*_*tic -4 c++ type-conversion stdstring

为什么std::to_string允许您将 a 转换doublestd::stringwhen std::is_convertible_v<double,std::string>is false?例如:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 9

is_convertible正在问一个关于两种类型之间的语言关系的非常具体的问题:源类型是否可以隐式转换为目标类型?而std::string作为一个类型没有隐式转换到double,所以答案是否定的。

std::to_string只是一个常规的旧功能。它不会在std::stringas a type 和之间创建任何关系double。是的,它在语义上将 a 转换double为 a string,但这不是 C++ 语言规则的隐式转换。就C++而言,它只是一个函数。

C++ 没有办法问这个问题,“是否有某个函数可以在某个地方将一个类型X的对象语义转换为一个类型的对象Y?” 如果这就是您要回答的问题,那么实际上并没有一种实用的方式来获得答案。


需要注意的是,隐式转换的概念非常特殊。隐式转换在很多地方都会自动发生。因此,如果一种类型可以隐式转换为另一种类型,那么这具有很强的意义。如果字符串可以隐式转换为双精度值,那么这在逻辑上意味着任何采用双精度值的函数也可以被赋予一个字符串。

许多语言认为这是合法的(尽管这些语言通常只是使用鸭子类型,所以它们通常没有“带双精度的函数”的概念,只有“带值的函数”);C++ 不是其中之一。如果你想执行字符串到双精度的转换,C++ 会让你把它拼出来。

类似地,从一种类型到另一种类型的隐式转换被认为是相关类型的固有属性。也就是说,为了从创建用户定义的转换XY,无论是XY必须具有限定该转换的成员函数。没有第三方代码可以在两种类型之间创建隐式转换。