简体   繁体   English

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

[英]Why can't I return a shared pointer in C++14 when the function return type is bool?

I'm using g++ and write a simple function: 我正在使用g ++并编写一个简单的函数:

#include <memory>

std::shared_ptr<char> ptr;

bool fails_compiling()
{
    return ptr;
}

From what I can see in the interface, the shared_ptr implementation includes a bool operator and I can even apply a quick fix like this: 从我在界面中看到的, shared_ptr实现包括一个bool操作符,我甚至可以应用这样的快速修复:

    return static_cast<bool>(ptr);

And it now compiles. 它现在编译。

Why would the return algorithm not attempt an auto-conversion to bool like the if() and while() do? 为什么返回算法不像if()while()那样尝试自动转换为bool

If you checkout std::shared_ptr 's bool conversion operator, you will see that it's declared as: 如果你签出std::shared_ptr的bool转换运算符,你会看到它被声明为:

explicit operator bool() const;

The use of explicit simply tells the compiler to forbid implicit conversion , which is what would have taken place because the return type of your function is different from the object type you are returning. 使用explicit只是告诉编译器禁止隐式转换 ,这是因为函数的返回类型与返回的对象类型不同而发生的情况。 However, this doesn't affect contextual conversions . 但是,这不会影响上下文转换

which occurs in the context of any: 发生在任何情况下:

  • controlling expression of if , while , for ; 控制ifwhilefor表达式;
  • the logical operators ! 逻辑运算符! , && and || &&|| ; ;
  • the conditional operator ?: ; 条件运算符?: ;
  • static_assert ; static_assert ;
  • noexcept . noexcept

above quote cited from cppreference 以上引用来自cppreference

Why would the return algorithm not attempt an auto-conversion to bool like the if() and while() do? 为什么返回算法不像if()while()那样尝试自动转换为bool

std::shared_ptr::operator bool is explicit conversion function, so implicit conversion is not allowed, but static_cast (explicit conversion) works well. std :: shared_ptr :: operator boolexplicit转换函数,因此不允许隐式转换,但static_cast (显式转换)效果很好。

When used for if or while , contextual conversions takes effect, then the explicit user-defined conversion function will be considered. 当用于ifwhile上下文转换生效,则将考虑显式的用户定义转换函数。 In this case, std::shared_ptr is contextually convertible to bool . 在这种情况下, std::shared_ptr可以在上下文中转换为bool

In the following five contexts, the type bool is expected and the implicit conversion sequence is built if the declaration bool t(e); 在以下五个上下文中,预期类型为bool ,如果声明bool t(e);则构建隐式转换序列bool t(e); is well-formed. 结构良好。 that is, the explicit user-defined conversion function such as explicit T::operator bool() const; 也就是说,显式的用户定义转换函数,如explicit T::operator bool() const; is considered. 被认为。 Such expression e is said to be contextually convertible to bool . 这种表达e被认为是在语境上可转换为bool

  • controlling expression of if, while, for; 控制if,while,for的表达式;
  • the logical operators !, && and ||; 逻辑运算符!,&&和||;
  • the conditional operator ?:; 条件运算符?:;
  • static_assert; static_assert;
  • noexcept. noexcept。

Why the code doesn't compile. 为什么代码不能编译。

std::shared_ptr 's conversion-to- bool operator is declared explicit and so will generally not be invoked for an implicit conversion. std::shared_ptr的conversion-to- bool运算符被声明为explicit ,因此通常不会为隐式转换调用。

In particular it will not be invoked in the context of a return statement. 特别是它不会在return语句的上下文中调用。

And it will not be considered for choosing a function overload, ie foo(p) will not resolve to an overload of foo that takes a bool argument. 并且它不会被考虑用于选择函数重载,即foo(p)将不会解析为带有bool参数的foo的重载。

There are however umpteen ways to express the conversion explicitly, including: 然而,有明确表达转换的方法,包括:

!!ptr

ptr != nullptr

ptr.get() != nullptr

static_cast<bool>( ptr )

ptr.operator bool()

The general case for implicit conversion to bool . 隐式转换为bool的一般情况。

There are some cases where explicit on an operator bool() is ignored , in order to make things work mainly as in C++03. 在某些情况下, operator bool() explicit忽略 ,以便使事情主要像在C ++ 03中那样工作。 That is, to make things work as with the schemes employed before explicit was allowed on conversion operators in C++11. 也就是说,在C ++ 11中允许转换运算符允许使用explicit之前使用的方案。 These exceptions are 这些例外是

  • use as a (grammar production) condition in an if , while or for , but not in a switch , ifwhilefor使用(语法生成) 条件 ,但不在switch

  • use as condition in :? 用作以下条件:? choice, static_assert or noexcept , choice, static_assertnoexcept

  • use as argument to the built-in boolean operators && , || 用作内置布尔运算符&&|| and ! 而且! , or their equivalents and , or and not . 或它们的等同物andornot

Notably, again, these exceptions that allow implicit conversion to bool in spite of explicit , known as contextual conversions , do not include a return statement expression. 值得注意的是,这些异常允许隐式转换为bool ,尽管有explicit ,称为上下文转换 ,但不包括return语句表达式。


Can explicit be ignored also in other cases? 在其他情况下也可以explicit被忽略吗?

In what other cases, if any, can explicit on a conversion operator be ignored? 在其他情况下,如果有的话,可以忽略转换运算符上的explicit吗?

Well, none. 好吧,没有。 But a non- explicit conversion operator, that is, an implicit conversion operator, can be invoked implicitly where the exact type to be converted to is not specified by the context. 但是,可以隐式调用非explicit转换运算符,即隐式转换运算符,其中上下文未指定要转换为的确切类型。

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

Certain language constructs require conversion to a value having one of a specified set of types appropriate to the construct. 某些语言结构需要转换为具有适合于构造的一组指定类型之一的值。 An expression e of class type E appearing in such a context is said to be contextually implicitly converted to a specified type T and is well-formed if and only if e can be implicitly converted to a type T that is determined as follows: E is searched for conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context. 出现在这样的上下文中的类类型E的表达式e被称为在上下文中隐式地转换为指定类型T并且当且仅当e可以被隐式转换为如下确定的类型T才是良好形式的: E是搜索返回类型为cv T或对cv T引用的转换函数,使得上下文允许T There shall be exactly one such T . 应该只有一个这样的T

For example, 例如,

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

If of class type, the operand [of delete ] is contextually implicitly converted (Clause 4) to a pointer to object type. 如果是类类型,则操作数[ delete ]在上下文中被隐式转换(第4节)到指向对象类型的指针。

… and so, a bit counter-intuitive to me!, the following should compile with a conforming compiler: ......所以,对我来说有点违反直觉!,以下内容应该使用符合标准的编译器进行编译:

 struct Foo { operator int*() const { return nullptr; } }; auto main() -> int { delete Foo(); } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM