Why can't I return a generic pointer in C ++ 14 when the return type of the function is bool?

I use g ++ and write a simple function:

#include <memory> std::shared_ptr<char> ptr; bool fails_compiling() { return ptr; } 

From what I see in the interface, the implementation of shared_ptr includes the bool operator, and I can even apply a quick fix like this:

  return static_cast<bool>(ptr); 

And now it compiles.

Why doesn't the return algorithm try to automatically convert to bool , for example, if() and while() do?

+7
c ++ return smart-pointers return-value boolean-expression
source share
3 answers

If you order the std::shared_ptr bool conversion operator, you will see that it is declared as:

 explicit operator bool() const; 

Using explicit simply tells the compiler to forbid implicit conversion , which is what happened because the type of the type you are returning is different from the return type of the object. However, this does not affect contextual transformations .

which occurs in the context of any:

  • control expression if , while , for ;
  • logical operators ! , && and || ;
  • conditional operator ?: ;
  • static_assert
  • noexcept .

above quotes from cppreference

+6
source share

Why wouldn't the return algorithm try to do the automatic conversion to bool like if() and while() do?

std :: shared_ptr :: operator bool is an explicit conversion function, so implicit conversion is not allowed, but static_cast (explicit conversion) works well.

When used for if or while , contextual conversions take effect, then an explicit user-defined conversion function will be considered. In this case, std::shared_ptr contextually converted to bool .

In the following five contexts, the bool type is expected, and an implicit conversion sequence will be constructed if the declaration is bool t(e); will be formed correctly. that is, an explicit user-defined transform function is considered, such as explicit T::operator bool() const; . Such an expression e is called contextually convertible to bool.

  • expression control if, while, for;
  • logical operators !, && and ||;
  • conditional operator?:;
  • static_assert
  • noexcept.
+2
source share

Why the code does not compile.

Operator

std::shared_ptr conversion-to- bool declared explicit and therefore will usually not be called for implicit conversion.

In particular, it will not be called in the context of the return .

And this will not be considered for the selection of the overload function, i.e. foo(p) will not allow overloading foo , which takes a bool argument.

However, there are many ways to express explicitly, including:

 !!ptr ptr != nullptr ptr.get() != nullptr static_cast<bool>( ptr ) ptr.operator bool() 

General case for implicit conversion to bool .

There are cases when explicit on operator bool() ignored in order to make the work work mainly as in C ++ 03. That is, everything works the same way as with the explicit schemes used earlier for conversion operators in C ++ 11. These exceptions:

  • use as a condition (for grammar) in if , while or for , but not in switch ,

  • use as condition in :? selecting static_assert or noexcept ,

  • use the built-in logical operators && , || as an argument and ! or their equivalents and , or and not .

It is noteworthy that these exceptions, which allow an implicit conversion to bool , despite explicit , called contextual transformations , do not include the expression of the return .


Is it possible to ignore explicit in other cases?

In what other cases, if any, can explicit ignore the conversion operator?

Well no. But the conversion operator is not explicit , i.e. An implicit conversion operator can be invoked implicitly where the exact type to be converted is not specified by the context.

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

" . For some language constructs, conversion to a value corresponding to one of the specified set of types to the construction is required. An expression e type of class e appearing in such a context is called contextually implicitly converted to the specified type T and is well formed if and only if e It can be converted implicitly to a type T , which is defined as follows: e is searched transformation functions, which is a return type cv T , or a reference to cv T , for which T is enabled context there must. It is exactly one such T .

For example,

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

" If the type is a class, the operand [from delete ] is contextually implicitly converted (section 4) to an object type pointer.

& hellip; and therefore, a little intuitive to me, the following should compile with the appropriate compiler:

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

All Articles