No viable conversion from std::function to bool - c++

The C++11 std::function is supposed to implement operator bool() const, so why does clang tell me there is no viable conversion?
#include <functional>
#include <cstdio>
inline double the_answer()
{ return 42.0; }
int main()
{
std::function<double()> f;
bool yes = (f = the_answer);
if (yes) printf("The answer is %.2f\n",f());
}
The compiling error is:
function_bool.cpp:12:7: error: no viable conversion from 'std::function<double ()>' to 'bool'
bool yes = (f = the_answer);
^ ~~~~~~~~~~~~~~~~
1 error generated.
EDIT I didn't see the explicit keyword.. no implicit conversion then, I guess I'll have to use static_cast.

operator bool() for std::function is explicit, therefore it cannot be used for copy-initialization. You can actually do direct-initialization:
bool yes(f = the_answer);
However, I assume it's really intended for contextual conversion, which happens when an expression is used as a condition, most often for an if statement. Contextual conversion can call explicit constructors and conversion functions, unlike implicit conversion.
// this is fine (although compiler might warn)
if (f = the_answer) {
// ...
}

Related

Is user-defined conversion to fundamental-type deletable?

template<typename Integral>
struct IntegralWrapper {
Integral _value;
IntegralWrapper() = default;
IntegralWrapper(Integral value)
: _value(value) {}
operator Integral() const {
return _value;
}
operator bool() const = delete;
};
int main() {
IntegralWrapper<int> i1, i2;
i1 * i2;
}
It's compiled successfully by gcc, but failed by MSVC and clang, with error overloaded operator '*' is ambiguous. The problem comes from the explicit deleted operator bool.
https://godbolt.org/z/nh6M11d98
Which side (gcc or clang/MSVC) is right? And why?
First of all: Deleting a function does not prevent it from being considered in overload resolution (with some minor exceptions not relevant here). The only effect of = delete is that the program will be ill-formed if the conversion function is chosen by overload resolution.
For the overload resolution:
There are candidate built-in overloads for the * operator for all pairs of promoted arithmetic types.
So, instead of using * we could also consider
auto mul(int a, int b) { return a*b; } // (1)
auto mul(long a, long b) { return a*b; } // (2)
// further overloads, also with non-matching parameter types
mul(i1, i2);
Notably there are no overloads including bool, since bool is promoted to int.
For (1) the chosen conversion function for both arguments is operator int() const instantiated from operator Integral() const since conversion from int to int is better than bool to int. (Or at least that seems to be the intent, see e.g. https://github.com/cplusplus/draft/issues/2288 and In overload resolution, does selection of a function that uses the ambiguous conversion sequence necessarily result in the call being ill-formed?).
For (2) however, neither conversion from int or bool to long is better than the other. As a result the implicit conversion sequences will for the purpose of overload resolution be the ambiguous conversion sequence. This conversion sequence is considered distinct from all other user-defined conversion sequences.
When then comparing which of the overloads is the better one, neither can be considered better than the other, because both use user-defined conversion sequences for both parameters, but the used conversion sequences are not comparable.
As a result overload resolution should fail. If I completed the list of built-in operator overloads I started above, nothing would change. The same logic applies to all of them.
So MSVC and Clang are correct to reject and GCC is wrong to accept. Interestingly with the explicit example of functions I gave above GCC does reject as expected.
To disallow implicit conversions to bool you could use a constrained conversion function template, which will not allow for another standard conversion sequence after the user-defined conversion:
template<std::same_as<int> T>
operator T() const { return _value; }
This will allow only conversions to int. If you can't use C++20, you will need to replace the concept with SFINAE via std::enable_if.

if code is using "implicit boolean conversions".can valid c++03 code, break in c++11?

With addition of change in c++11
change:Change: Specify use of explicit in existing boolean conversion operators
(https://timsong-cpp.github.io/cppwp/n4618/diff.cpp03.input.output)
can valid c++03 code break in c++11?
struct abt {
public:
abt(int a, double b){}
abt(int a){cout<<"int"<<endl;}
abt(bool b) {cout<<"bool"<<endl;}
abt(bool b,bool c) {cout<<"bool bool"<<endl;}
operator bool() const { return true; } };
int main() {
abt is("a",3);
if (is)
std::cout << "success";
if( is == true)
std::cout << "success";
return 0;
}
this valid c++03 code giving same output in c++11,output with implicit boolean conversion is also same in in c++11. Is there smthing wrong with rule ?
Even if your abt would have only an explicit converion if(is) would be fine in C++11, because the condition of an if is a context where explicit conversions are "implicit". From cppreference:
In the following contexts, the type bool is expected and the implicit
conversion is performed if the declaration bool t(e); is well-formed
(that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be
contextually converted to bool.
the controlling expression of if, while, for;
...
What changed in C++11 is this and many implicit conversions to bool of standard types changed to explicit conversions. For example std::istream::operator bool:
operator void*() const; (1) (until C++11)
explicit operator bool() const; (2) (since C++11)
Code that was always wrong, but compiled before will now fail to compile, which is good. For example:
#include <iostream>
void foo(bool){}
int main()
{
foo(std::cout);
}
Live Demo
On the other hand, if you wrote code like this and the implicit conversion was intentional, then your code breaks in C++11.
TL;DR:
This is not a breaking change for if(is). If it was fine before it is fine now (whether is is your custom type with an conversion to bool or a standard type, and irrespective of wether the conversion is explicit or not).
If you rely too much on implcit conversions of standard types you might encounter one or two surprises though.

Why std::function does not implicitly convert to bool in C++11? [duplicate]

This question already has an answer here:
No viable conversion from std::function to bool
(1 answer)
Closed 6 years ago.
Consider the following code.
#include <functional>
int main(void)
{
std::function<void()> f1;
if (f1) { /* ok */
...
}
bool b = f1; /* compile-error */
bool B = !f1; /* ok */
...
}
std::function<> converts implicitly to bool in some circumstances but not in all of them. Assigning it to a bool-variable does not work, whereas the result of an operation or using it in an if()-statement is OK.
Why is that so? It seems we have to do an boolean-operation on it, then the conversion works.
What I did to make work the b = f1-line is the good ol' double bang: !!. It looks like an antique in such modern C++-code.
EDIT: This compiles as well:
bool b = f1 || f1; /* OK */
Note that std::function::operator bool is explicit conversion function, implicit conversion is not allowed. So bool b = f1; won't work. (Explicit conversion will work well if you use static_cast like bool b = static_cast<bool>(f1);.)
using it in an if()-statement is OK.
When being used with if, operator! or operator||, contextual conversions will take effect, and the explicit conversion function will be considered.
(since C++11)
In the following five contexts, the type bool is expected and the implicit conversion sequence is built if the declaration bool t(e); is well-formed. that is, the explicit user-defined conversion function such as explicit T::operator bool() const; is considered. Such expression e is said to be contextually convertible to bool.
controlling expression of if, while, for;
the logical operators !, && and ||;
the conditional operator ?:;
static_assert;
noexcept.

Position/Order of move constructor within class matters? Templated cast operator in conjunction with move constructor

This looks like a compiler bug, but the case is so simple I am a bit skeptical, so I am looking for a confirmation. Reproducible with both VS2010 and VS2012.
The below example does not compile. This error is given:
Error 1 error C2440: 'type cast' : cannot convert from
'ConvertibleToAny' to 'OtherType<_Ty>' test.cpp 40
If you move the position of the move constructor OtherType(ThisType &&) above the constructor OtherType( int ), it suddenly compiles.
#include "stdafx.h"
#include <string>
using namespace std;
template<class _Ty>
struct OtherType
{
typedef OtherType<_Ty> ThisType;
OtherType()
{
}
OtherType( int )
{
}
// The move constructor
OtherType(ThisType && )
{
}
};
struct ConvertibleToAny
{
template <class AnyType>
operator AnyType()
{
return AnyType();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
(OtherType<wstring>) ConvertibleToAny();
return 0;
}
Is this a bug or is this expected behavior? If it's expected, please quote the relevant paragraph from the C++11 specification.
I already posted this as a bug at Microsoft Connect, click here to open it.
Your expression
(OtherType<wstring>) ConvertibleToAny()
is a unary explicit cast (5.4) from a temporary of user-defined type to a user-defined type, interpreted per 5.4:4 as a static_cast:
static_cast<OtherType<wstring>>(ConvertibleToAny())
which per 5.2.9:4 has the validity of initializing a temporary variable t:
OtherType<wstring> t(ConvertibleToAny())
This is direct-initialization (8.5:15) and as such (8.5:16) all the one-argument constructors of OtherType participate in overload resolution per the rules in 13.3.1.3.
Following 13.3:2, both the int and move constructors are available and are viable per 13.3.2, so we have two possible implicit conversion sequences (13.3.3.1) for the single argument:
ConvertibleToAny [temporary] -> int
ConvertibleToAny [temporary] -> OtherType<wstring> &&
Following 13.3.3.1.2 there is no ordering between these sequences, so there is no best viable function, overload resolution fails (13.3:3), and the program is ill-formed.
If the conversion function (12.3.2) is made explicit (12.3.2:2) then it is only considered for direct-initialization. Although implicit conversion sequences (13.3.3.1) are implicit conversions (4:3) and so involve copy-initialization, the intent of the standard in the example to 12.3.2:2 is clearly that explicit conversion functions should be considered in this case; as such, it appears again that overload resolution should fail.

When to use conversion operators?

Considering the following example, the line int a = objT + 5; gives ambiguous conversion which is handled in two ways, using the explicit cast which i think shouldn't be necessary and replacing the use of conversion operators with member functions instead. and here, my question becomes should you still use conversions operators or not at all?
class Testable {
public:
Testable(int val = 0):x(val){}
operator int() const { return x; }
operator double() const { return x; }
int toInt() { return x; }
double toDouble() { return x; }
private:
int x;
};
int main()
{
Testable objT(10);
// ambiguous conversion
int a = objT + 5;
// why to use explicit cast when
// the conversion operator is for to handle
// this automatically
int b = static_cast<int>(objT) + 5;
// member functions
int c = objT.toInt() + 5;
}
Note that int d = objT; is unambiguous, as is double e = objT; Here the compiler can unambiguously choose a conversion operator because of the exact match between the type of the left hand side and the return types from those conversion operators.
The ambiguous conversion results from objT + 5 (also note: long f = objT; is also ambiguous). The problem is that you've taken away the essential information the compiler needs to mindlessly perform the disambiguation.
The problem goes away if you get rid of either of those conversion operators. Since the underlying data member is an int, I suggest getting rid of operator double().
For your particular case, you could just provide the conversion to double, since it has a standard conversion to int. However, implicit conversions often do more harm than help. If you use them, then avoid having both the conversion from int (your non explicit constructor) and to int, which I think is the source of your current problem.
This question is similar to mine, whether is it possible to change the precedence of implicit conversion operators. Unfortunately there is no satisfactory solution, there is no precedence amongst implicit conversions.
One solution is to have additional overload(s) to the ambiguous function or operator, in your case they are operator + (const Testable&, int) and operator + (const Testable&, double).
Another solution is to simply leave only one implicit conversion, in your case the integer one would be best.
Only use implicit conversion when you desperately need automatic conversion to the given type. Explicit toInt, toDouble functions are MUCH better, they clarify the code and do not hide potential pitfalls. Use the explicit keyword for unary constructors, they block implicit conversion via that constructor.
And no, it is not possible to chain implicit conversions, neither if they are operators nor constructors. The C++ standard mandates only 1 implicit conversion can be in a conversion sequence.
You don't need implicit conversion to double. You always return decimal value and compiler can combine multiple implicit conversion operators.
If your private property x of type int were a double, I would recommend not to use implicit conversion to int since it would cause precision loss.