How to return an std::optional lambda? - c++

How can I declare a function that returns an std::optional lambda? e.g.
<what_do_i_put_here?> foo(bool b) {
if(b) return std::nullopt;
return [](int) { ... };
}

How about using the ternary operator? It will automatically deduce the correct optional type
#include <optional>
auto foo(bool b) {
return b ? std::nullopt : std::optional{[](int){}};
}

You can add a level of indirection to deduce the type via auto and decltype:
#include <optional>
auto foo_impl(){
return [](int){};
}
std::optional<decltype(foo_impl())> foo(bool b) {
if(b) return std::nullopt;
return foo_impl();
}

You can do it something like the following
#include <iostream>
#include <optional>
auto f( bool b )
{
auto l = [] { std::cout << "Hello World!"; };
std::optional<decltype( l )> opt;
if (b)
{
// some code
opt = l;
}
else
{
// some other cod
}
return opt;
}
int main()
{
( *f( true ) )( );
}
Another way is to use std::function with std::optional as for example
std::optional<std::function<void( int )>> g( bool b )
{
if (b)
{
return std::function<void( int )>( []( int x ) { std::cout << x; } );
}
else
{
return std::function<void( int )>( []( int x ) { std::cout << 2 * x; } );
}
}

In the upcoming C++23 you can avoid an extra function while only constructing your lambda in case it is needed. Unfortunately, support for this is currently experimental:
#include <optional>
auto foo(bool const b) {
return (b ? std::optional<bool>(true) : std::optional<bool>())
.transform([](bool){
return [](int){ return 42;};
});
}
(demo with gcc trunk)
This uses the new std::optional<T>::transform(F) member function.

Related

function-style-cast in Template Meta programming

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 to bool (via conversion to function pointer). You can add an additional templated constructor to make compiler prefer conversion to std::function:
template <typename F,
typename = std::enable_if_t<std::is_convertible_v<F,std::function<bool()>>>>
async_bool(F checkIt): check(checkIt) { }
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.

setting return of coroutine into a variable inside another coroutine makes compiler try to convert promise types

I am currently on an issue where I simply try to co_await coroutine B to save the return of it into a variable inside coroutine A but it tries to convert the promise type of A to the promise type of B.
forStackoverflow.cpp: In function ‘myTask<std::optional<int> > getValue(std::vector<int>&, int, bool)’:
forStackoverflow.cpp:68:60: error: cannot convert ‘coroutine_handle<promise_type<std::optional<int>>>’ to ‘coroutine_handle<promise_type<int>>’
68 | leaf = co_await suspendableLocateValue(key, array, true);
| ^
forStackoverflow.cpp:42:58: note: initializing argument 1 of ‘void myTask<T>::await_suspend(std::__n4861::coroutine_handle<myTask<T>::promise_type>) const [with T = int]’
42 | void await_suspend(std::coroutine_handle<promise_type> coro) const noexcept { coro.promise().boolIsDone = true; }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
#include <iostream>
#include <optional>
#include <utility>
#include <vector>
#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
#include <vector>
template <typename T>
struct myTask {
struct promise_type {
T value_;
~promise_type() {}
myTask<T> get_return_object() {
return myTask<T> {
.h_ = std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_always final_suspend()
{
boolIsDone = true;
return {};
}
void unhandled_exception() { std::terminate(); }
std::suspend_always return_value(auto value) {
value_ = value;
return {};
}
bool boolIsDone = false;
auto isDone() { return boolIsDone; }
};
bool await_ready() const noexcept { return false; }
void await_suspend(std::coroutine_handle<promise_type> coro) const noexcept { coro.promise().boolIsDone = true; }
void await_resume() const noexcept {}
std::coroutine_handle<promise_type> h_;
operator std::coroutine_handle<promise_type>() const { return h_; }
};
myTask<int> suspendableLocateValue(int key, std::vector<int>& array, bool interleave)
{
int currentInt = 0;
if (interleave = true)
{
//do something here
co_await std::suspend_always{};
}
currentInt = array.at(key);
co_return currentInt;
}
myTask<std::optional<int>> getValue(std::vector<int>& array, int key, bool interleave)
{
//int result = array.at(key);
int leaf;
if (interleave = true)
{
leaf = co_await suspendableLocateValue(key, array, true);
}
co_return std::make_optional(leaf);
}
void minimalInterleavedExecution(std::vector<int>& lookup,
std::vector<int>& keys,
std::vector<std::optional<int>>& results,
int groupsize)
{
std::vector<std::coroutine_handle<myTask<std::optional<int>>::promise_type>> handles;
for (int i = 0; i < groupsize; ++i)
{
handles.push_back(getValue(lookup, keys.at(i), true));
}
int notDone = groupsize;
int i = groupsize;
while (notDone > 0)
{
for (int handleIndex = 0; handleIndex < handles.size(); ++handleIndex)
{
if (!handles.at(handleIndex).promise().isDone())
{
handles.at(handleIndex).resume();
}
else
{
results.push_back(handles.at(handleIndex).promise().value_);
if (i < keys.size())
{
handles.at(handleIndex) = getValue(lookup, keys.at(i), true);
++i;
}
else
{
--notDone;
handles.erase(handles.begin() + handleIndex);
--handleIndex;
}
}
}
}
}
int main()
{
std::vector<int> lookup = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
std::vector<int> keys = {4, 2, 0, 6, 9, 0};
std::vector<std::optional<int>> results;
minimalInterleavedExecution(lookup, keys, results, 4);
}
My original code actually involves a B+Tree and suspendableLocateValue is supposed to be a function that finds and returns a leaf of type myTask<Node> with a given key and getValue is supposed to set the return value of the Node-returning function to a new Node and gets the specific value from the node to return it as an optional.
In function with return value of myTask<std::optional<int>> there is a call
leaf = co_await suspendableLocateValue(key, array, true);
and suspendableLocateValue returns myTask<int>. But await_suspend is not templated and therefore could not be used:
void await_suspend(std::coroutine_handle<promise_type> coro) const noexcept
So myTask<U> could be awaited only in myTask<U> coroutines.
When co_await something is encountered in the coroutine there are several steps that compiler do to determine what is the meaning of that expression:
Is there await_transform in enclosing coroutine?
Is there operator co_await?
Otherwise (your case) it generates code that has something.await_suspend(h), where h is a std::coroutine_handle<P> and P is a type of an enclosing coroutine's promise.
In your example:
something is myTask<int>
h is std::coroutine_handle<myTask<std::optional<int>>::promise_type>
so there is a call to myTask<int>::await_suspend(std::coroutine_handle<myTask<std::optional<int>>::promise_type>) but there is no such function. Compiler tries to convert std::coroutine_handle<myTask<std::optional<int>>::promise_type> to actual argument type of await_suspend (std::coroutine_handle<myTask<int>::promise_type>) and writes an error about it.

Idiomatic way to initialise std::optional from another std::optional and something else

I want to initialise an std::optional from another std::optional and some additional arguments provided that the latter std::optional is not empty. Unfortunately std::optional::optional 4) and 5) are not suitable as the amount of arguments is different.
I was able to come up with the following, but it still feels excessive. I particularly don't like specifying return type for the lambda explicitly.
Is there an better (as in more succinct and more expressive) way to achieve this?
#include <iostream>
#include <optional>
#include <tuple>
struct A {
A(std::optional<int> oi, float f, char c)
:
val{
[&] () -> decltype(val) /* I don't like specifying type here */ {
if (oi)
return {{*oi, f, c}};
else
return std::nullopt;
}()
}
{
}
std::optional<std::tuple<int, float, char>> val;
};
int main()
{
auto print = [](auto& r) {
if (r)
std::cout
<< std::get<0>(*r) << "; "
<< std::get<1>(*r) << "; "
<< std::get<2>(*r) << std::endl;
else
std::cout << "nullopt" << std::endl;
};
auto one = A({}, 1.0, 'c');
print(one.val);
auto two = A(10, 2.0, 'c');
print(two.val);
}
Live example.
Just trust the compiler to do the right thing:
A(std::optional<int> oi, float f, char c) {
if (oi) {
val.emplace(*oi, f, c);
}
}
This is also of course a great use-case for a map() member function†, which you can write as a non-member function:
A(std::optional<int> oi, float f, char c)
: val(map(oi, [&](int i){ return std::tuple(i, f, c); }))
{ }
†Recently proposed in P0798 by TartanLlama.

Assign first value that is not zero (c++)

In JavaScript you can write this:
var foo = value1 || value2.
The result is a new value that is value1 if value1 is not zero and value2 if value1 is zero.
In C++ this expression is evaluated to true or false instead.
Is there a way to imitate this syntax somehow in c++? (for unlimited number of values).
auto foo = value1 ? value1 : value2;
There's no easy way to extend it.
You could use write a generic function that would accept any number of arguments:
#include <initializer_list>
#include <iostream>
int find_first(std::initializer_list<int> args) {
for(int arg : args) {
if (arg) {
return arg;
}
}
return -1;
}
int main(int argc, char** argv) {
std::cout << find_first({0, 0, 1, 2}) << std::endl;
std::cout << find_first({3}) << std::endl;
std::cout << find_first({-1, -2, 0}) << std::endl;
return 0;
}
This prints:
1
3
-1
You could use the ternary operator
int i = (value1 != 0 ? value1 : value2)
This evaluates to
int i;
if (value1 != 0)
i = value1;
else
i = value2;
And the syntax is
(condition ? trueOutput : falseOutput)
Ok so best I could come up with so far is an improvement of the jterrace solution.. :) So far it works with a type Foo that can be assigned from int. This allows the solution to work with a list that consists of objects of multiple types that can all be compared to foo.
Is there anything I can improve further to make this the most generic solution possible?
#include <initializer_list>
#include <iostream>
#include <stdio.h>
class Foo {
public:
Foo(int v){val = v;}
bool operator==(int v) const {return val == v;}
bool operator!=(int v) const {return val != v;}
operator int() const {return val;}
int val;
};
template<class Type>
Type find_first(std::initializer_list<Type> args) {
auto it = args.begin();
for(int c = 0; c < args.size(); c++) {
if (*it != 0) {
return *it;
}
if(c == args.size() - 1) return *it;
it++;
}
// only get here if size == 0
return Type(0);
}
int main(int argc, char** argv) {
Foo *foo = new Foo(0);
Foo bar = 0;
std::cout << find_first<Foo>({*foo, bar, 1}).val << std::endl;
std::cout << find_first<int>({*foo, bar, (int)3.0f}) << std::endl;
return 0;
}

using of std::accumulate

Need prettier solution of below example but with std::accumulate.
#include <algorithm>
#include <vector>
#include <iostream>
class Object
{
public:
Object( double a, double b ):
a_( a ),
b_( b )
{}
double GetA() const { return a_; }
double GetB() const { return b_; }
// other methods
private:
double a_;
double b_;
};
class Calculator
{
public:
Calculator( double& result ):
result_( result )
{}
void operator() ( const Object& object )
{
// some formula
result_ += object.GetA() * object.GetB();
}
private:
double& result_;
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = 0.0;
std::for_each( collection.begin(), collection.end(),
Calculator( result ) );
std::cout << "result = " << result << std::endl;
return 0;
}
do changes in Calculator and main function.
struct Calculator
{
double operator() ( double result, const Object& obj )
{
return result + ( obj.GetA() * obj.GetB());
}
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = std::accumulate( collection.begin(), collection.end(), 0, Calculator() );
std::cout << "result = " << result << std::endl;
return 0;
}
also it could be better:
double sumABProduct( double result, const Object& obj )
{
return result + ( obj.GetA() * obj.GetB());
}
double result = std::accumulate( collection.begin(), collection.end(), 0, sumABProduct );
Update 2: Boost.Lambda makes this a piece of cake:
// headers
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
// ...
cout << accumulate(dv.begin(), dv.end(),
0,
_1 += bind(&strange::value, _2)) //strange defined below
<< endl;
Update: This has been bugging me for a while. I can't just get any of the STL algorithms to work in a decent manner. So, I rolled my own:
// include whatever ...
using namespace std;
// custom accumulator that computes a result of the
// form: result += object.method();
// all other members same as that of std::accumulate
template <class I, class V, class Fn1, class Fn2>
V accumulate2(I first, I last, V val, Fn1 op, Fn2 memfn) {
for (; first != last; ++first)
val = op(val, memfn(*first));
return val;
}
struct strange {
strange(int a, int b) : _a(a), _b(b) {}
int value() { return _a + 10 * _b; }
int _a, _b;
};
int main() {
std::vector<strange> dv;
dv.push_back(strange(1, 3));
dv.push_back(strange(4, 6));
dv.push_back(strange(20, -11));
cout << accumulate2(dv.begin(), dv.end(),
0, std::plus<int>(),
mem_fun_ref(&strange::value)) << endl;
}
Of course, the original solution still holds:
The easiest is to implement an operator+. In this case:
double operator+(double v, Object const& x) {
return v + x.a_;
}
and make it a friend of Object or member (look up why you may prefer one over the other):
class Object
{
//...
friend double operator+(double v, Object const& x);
and you're done with:
result = accumulate(collection.begin(), collection.end(), 0.0);
My earlier approach doesn't work because we need a binary_function.
std::accumulate manual.
here is an issue here, I guess the arguments are written in the wrong order should be:
result = std::accumulate(collection.begin(), collection.end(), Object(0),Adapt())
where Adapt is defined thus:
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static Object operator()(Object const &x, Object const &y) {
return Object(mul(x)+mul(y)) ; } };
in this case of accumulate, the result is contained in a returned Object.
If you are using gnu parallel mode the functor will give you problems if the result and the actual object referred to by the iterator are different.
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static double operator()(Object const &x, Object const &y) {
return mul(x)+mul(y) ; } };
result = std::accumulate(collection.begin(), collection.end(), 0.0,Adapt())
will not work with gnu parallel mode for some strange and silly reason.
Using c++0x:
#include <numeric>
#include <vector>
#include <iostream>
class Object
{
public:
Object( double a, double b ):
a_( a ),
b_( b )
{}
double GetA() const { return a_; }
double GetB() const { return b_; }
// other methods
private:
double a_;
double b_;
};
int main()
{
std::vector< Object > collection;
collection.push_back( Object( 1, 2 ) );
collection.push_back( Object( 3, 4 ) );
double result = std::accumulate( collection.begin(), collection.end(), 0,
[] (double result, const Object& obj)
{
return result + obj.GetA() * obj.GetB();
}
);
std::cout << "result = " << result << std::endl;
return 0;
}
One would hope this is homework...
struct Adapt {
static double mul(Object const &x) { return x.GetA() * x.GetB(); }
static double operator()(Object const &x, Object const &y) {
return mul(x)+mul(y); } };
and
result = std::accumulate(collection.begin(), collection.end(), Object(0,0),Adapt() );
assuming you're not allowed to touch the declaration of Object.