不同gcc版本的bool到字符串转换的不同行为

时间:2019-06-20 07:01:57

标签: c++ string gcc gcc-warning

我知道我不应该这样做,但是我仍然想知道它是如何工作的。

我正在尝试编译一个错误的代码,其中函数的返回类型为std::string,而实际上我正在返回一个布尔值:

// test.cpp
std::string donothing(int i)
{
  return false;
}

我知道这行不通,并且应该在编译器中捕获错误,但是有一个有趣的发现:

  1. 使用gcc 4.8.5,我可以摆脱警告和编译工作。
  2. 使用gcc 7.3.1时,编译失败。

以下是编译器的输出:

// 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;
             ^~~~~

1 个答案:

答案 0 :(得分:1)

GCC 7.3.1

默认情况下,GCC 7.3.1使用func didReceive(_ element: Element) { data.append(element) onElementReceival() } 。 (我找不到GCC 7.3.1手册,但FWIW的GCC 7.4 manualGCC 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*构造函数可以满足条件,但是由于它显然无关紧要,因此将其省略。

GCC 4.8.5

[lex.bool]

  

如果未提供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