当函数返回类型为bool时,为什么我不能在C ++ 14中返回共享指针?

时间:2016-09-19 00:42:22

标签: c++ return return-value smart-pointers boolean-expression

我正在使用g ++编写一个简单的函数:

#include <memory>

std::shared_ptr<char> ptr;

bool fails_compiling()
{
    return ptr;
}

从我在界面中看到的内容,shared_ptr实现包含bool运算符,我甚至可以应用这样的快速修复:

    return static_cast<bool>(ptr);

它现在编译。

为什么返回算法不会像boolif()那样尝试自动转换为while()

3 个答案:

答案 0 :(得分:6)

如果你签出std::shared_ptr的bool转换运算符,你会看到它被声明为:

explicit operator bool() const;

使用explicit只是告诉编译器禁止implicit conversion,这是因为函数的返回类型与返回的对象类型不同而发生的情况。但是,这不会影响contextual conversions

发生在任何上下文中:

  
      
  • 控制ifwhilefor;
  • 的表达   
  • 逻辑运算符!&&||;
  •   
  • 条件运算符?:;
  •   
  • static_assert;
  •   
  • noexcept
  •   

以上引用自cppreference

答案 1 :(得分:2)

  

为什么返回算法不会像boolif()那样尝试自动转换为while()

std::shared_ptr::operator boolexplicit转换函数,因此不允许隐式转换,但static_cast(显式转换)效果很好。

当用于ifwhile时,contextual conversions生效,则会考虑显式的用户定义转换函数。在这种情况下,std::shared_ptr 可在上下文中转换为bool

  

在以下五个上下文中,类型bool是预期的,如果声明bool t(e);格式正确,则构建隐式转换序列。也就是说,考虑了显式的用户定义转换函数,例如explicit T::operator bool() const;。这样的表达式e被认为是在语境上可转换为bool

     
      
  • 控制if,while,for;
  • 的表达式   
  • 逻辑运营商!,&amp;&amp;和||;
  •   
  • 条件运算符?:;
  •   
  • static_assert;
  •   
  • noexcept。
  •   

答案 2 :(得分:1)

为什么代码无法编译。

std::shared_ptr转换为 - bool运算符被声明为explicit,因此通常不会为隐式转换调用。

特别是它不会在return语句的上下文中调用。

并且不会考虑选择函数重载,即foo(p)将无法解析为foo的重载bool

然而,有明确表达转换的方法,包括:

!!ptr

ptr != nullptr

ptr.get() != nullptr

static_cast<bool>( ptr )

ptr.operator bool()

隐式转换为bool

的一般情况

在某些情况下,explicit上的operator bool()忽略,以便使主要工作与C ++ 03一样。也就是说,让事情像C ++ 11中转换运算符允许explicit之前使用的方案一样工作。这些例外是

  • ifwhilefor中使用(语法制作)条件,但不在switch中使用,

  • :?选项,static_assertnoexcept

  • 中用作条件
  • 用作内置布尔运算符&&||!或其等价物andor和{的参数{1}}。

值得注意的是,这些异常允许隐式转换为not,而不是bool,称为上下文转换,但不包含explicit语句表达

在其他情况下还可以忽略return吗?

在其他情况下(如果有的话),可以忽略转换运算符上的explicit吗?

嗯,没有。但是,非explicit转换运算符(即隐式转换运算符)可以隐式调用,而上下文不指定要转换为的确切类型。

C ++11§4/ 5(转):
  

某些语言结构需要转换为具有适当的指定类型集之一的值   到构造。在这样的上下文中出现的类类型explicit的表达式e被称为 上下文隐式转换 到指定的类型E当且仅当T可以隐式转换为时,格式良好   类型e,其确定如下:T搜索返回类型为 cv E的转换函数或对 cv T,以便上下文允许T。应该只有一个T

例如,

C ++11§5.3.5/ 1(expr.delete):
  

如果是类类型,[{1}}]的操作数是上下文的   隐式转换(第4节)到指向对象类型的指针。

...等等,对我来说有点反直觉!以下应该使用符合标准的编译器进行编译:

T