| Home | Libraries | People | FAQ | More

#### 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
        chanp->close();
        return value;
    }

It might be called like this:

    boost::variant< std::string, double, int > result =
        wait_first_value_het(
                [](){ 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);