Code taken from the book Template Metaprogramming with C++, it doesn't compile i tried visual studio 22 i get the error:
Error C2440
\<function-style-cast\>'
: cannot convert from 'initializer list' to 'n713::async_bool'chapter_07
see code:
class async_bool{
std::function<bool()> check;
public:explicit async_bool() = delete;
async_bool(std::function<bool()> checkIt): check(checkIt){ }
async_bool(bool val)
: check([val]() {return val; })
{ }
static async_bool yes() {
return async_bool(
[]() { return true; } );
}
static async_bool no() {
return async_bool(
[]() { return false; } );
}
bool operator&&(bool fore) const { return fore && check(); }
bool operator!() const { return !check(); }
operator bool() const { return check(); }
};
int main(){
async_bool b1 = async_bool(false); //async_bool b1{ false };
async_bool b2 = async_bool(true);// async_bool b2{ true };
async_bool b3{ {std::cout << "Y/N? "; char c; std::cin >> c; return c == 'Y' || c == 'y'; }
if (b1) { std::cout << "b1 is true\n"; }
if (b2) { std::cout << "b2 is true\n"; }
if (b3) { std::cout << "b3 is true\n"; }
return 0;
};
tried c++20 with visual studio tried g++ in ubuntu-> gave different errors but still didnt compile, managed to fix it i think by changing the code to the following:
class async_bool
{
using check = std::function<bool()>;
check dec_;
public:
async_bool() = delete;
async_bool(check dec) : dec_{ std::move(dec) } {}
async_bool(bool val) :dec_([val]() {return val; }) {}
static async_bool yes() {
const auto lam = []() { return true; };
async_bool async_bool_yes(lam());
return async_bool_yes;
}
static async_bool no() {
const auto lam = []() { return false; };
async_bool async_bool_no(lam());
return async_bool_no;
}
bool operator&&(bool fore) const { return fore && dec_(); }
bool operator!() const { return !dec_(); }
operator bool() const { return dec_(); }
};
and in main:
int main()
{
async_bool b1( false );
async_bool b2{ true };
const auto lam = []() { []() {std::cout << "Y/N? "; char c; std::cin >> c; return c == 'Y' || c == 'y'; }; };
async_bool b3{lam};
return 0;
}
Lambdas that don't capture anything are convertible both to
std::function
and tobool
(via conversion to function pointer). You can add an additional templated constructor to make compiler prefer conversion tostd::function
:Alternatively, instead of SFINAE you can use concepts.
(Edit: it's interesting that removing the constructor from std::function removes the ambiguity, but every construction with a
{ <captureless-lambda> }
still fails because conversion from a function pointer to a bool is forbidden using braces, but the corresponding candidate it is not removed from overload-set. Maybe language lawyers can explain this bit if you're interested.