Boost C++ Libraries of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.

when_any, heterogeneous types

We would be remiss to ignore the case in which the various task functions have distinct return types. That means that the value returned by the first of them might have any one of those types. We can express that with Boost.Variant.

To keep the example simple, we'll revert to pretending that none of them can throw an exception. That makes wait_first_value_het() strongly resemble wait_first_value(). We can actually reuse wait_first_value_impl(), merely passing boost::variant<T0, T1, ...> as the queue's value type rather than the common T!

Naturally this could be extended to use wait_first_success() semantics instead.

// No need to break out the first Fn for interface function: let the compiler
// complain if empty.
// Our functions have different return types, and we might have to return any
// of them. Use a variant, expanding std::result_of<Fn()>::type for each Fn in
// parameter pack.
template< typename ... Fns >
boost::variant< typename std::result_of< Fns() >::type ... >
wait_first_value_het( Fns && ... functions) {
    // Use buffered_channel<boost::variant<T1, T2, ...>>; see remarks above.
    typedef boost::variant< typename std::result_of< Fns() >::type ... > return_t;
    typedef boost::fibers::buffered_channel< return_t > channel_t;
    auto chanp( std::make_shared< channel_t >( 64) );
    // launch all the relevant fibers
    wait_first_value_impl< return_t >( chanp,
                                       std::forward< Fns >( functions) ... );
    // retrieve the first value
    return_t value( chanp->value_pop() );
    // close the channel: no subsequent push() has to succeed
    return value;

It might be called like this:

boost::variant< std::string, double, int > result =
            [](){ return sleeper("wfvh_third",  150); },
            [](){ return sleeper(3.14,          100); },
            [](){ return sleeper(17,             50); });
std::cout << "wait_first_value_het() => " << result << std::endl;
assert(boost::get< int >( result) == 17);