我知道我不应该这样做,但是我仍然想知道它是如何工作的。
我正在尝试编译一个错误的代码,其中函数的返回类型为std::string
,而实际上我正在返回一个布尔值:
// test.cpp
std::string donothing(int i)
{
return false;
}
我知道这行不通,并且应该在编译器中捕获错误,但是有一个有趣的发现:
以下是编译器的输出:
// gcc 4.8.5
test.cpp: In member function ‘virtual std::string donothing(int)’:
test.cpp:9:9: warning: converting ‘false’ to pointer type for argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-Wconversion-null]
return false;
// gcc 7.3.1
test.cpp: In member function ‘virtual std::__cxx11::donothing(int)’:
test.cpp:9:9: error: could not convert ‘false’ from ‘bool’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return false;
^~~~~
答案 0 :(得分:1)
默认情况下,GCC 7.3.1使用func didReceive(_ element: Element) {
data.append(element)
onElementReceival()
}
。 (我找不到GCC 7.3.1手册,但FWIW的GCC 7.4 manual和GCC 6.5 manual都这样说。)
让我们看一下C ++ 14([basic.string])中类-std=gnu++14
的提要。唯一接收一个参数的转换(非显式)构造函数是: 1
basic_string
因此,问题本质上是:basic_string(const charT* s, const Allocator& a = Allocator());
无法隐式转换为false
。根据{{3}}:
空指针常量是具有以下内容的整数文字([lex.icon]) 值为零或类型为
const char*
的prvalue。空指针 常量可以转换为指针类型;结果是 null 该类型的指针值,并且彼此可以区分 对象指针或函数指针类型的值。这样的转换是 称为空指针转换。的两个空指针值 同一类型应比较相等。空指针的转换 指向cv限定类型的指针的常量是一次转换,并且 不是指针转换后跟限定符的顺序 转换([conv.qual])。整型的空指针常量可以 转换为std::nullptr_t
类型的prvalue。 [注意: 结果prvalue不是空指针值。 — 尾注]
std::nullptr_t
是布尔文字([conv.ptr]/1)而不是整数文字。因此,false
无法隐式转换为false
。
1 实际上,有一个const char*
构造函数可以满足条件,但是由于它显然无关紧要,因此将其省略。
如果未提供C ++语言方言选项,则默认值为
initializer_list
。
同样,让我们看一下C ++ 98(GCC 4.8.5 manual)中类-std=gnu++98
的提要。唯一接收一个参数的转换(非显式)构造函数是:
basic_string
因此,问题本质上是:basic_string(const charT* s, const Allocator& a = Allocator());
可以隐式转换为false
。根据{{3}}:
空指针常量是整数常量表达式 ([lib.basic.string]) 整数类型的右值,值为零。空指针 常量可以转换为指针类型;结果是 null 该类型的指针值,并且彼此可以区分 指向对象或函数类型的指针的值。两个空 相同类型的指针值应比较相等。的转换 指向cv限定类型的指针的空指针常量是单个 转换,而不是指针转换的顺序,后跟一个 资格转换 ([conv.ptr]/1)。
const char*
是整数类型(false
是整数类型)的整型常量表达式右值,其值为零。因此,bool
可以隐式转换为false
。