简体   繁体   中英

Get the result type of a std::future in a std::function

Suppose a instance of std:::future<T> f , how can I get the type T out of it for meta programming like decltype(f)::result_type ? And how to get the type if this std::future<T> is in a std::function<void(std::future<T>)> c ?

std::function<T()> for example has the member type result_type and first_argument_type (although deprecated) but I can not find any thing similar for std::future .

My minimized use case:

#include <future>
#include <functional>

#include <iostream>

template<typename T>
using callback_t = std::function<void(std::future<T>)>;

void foo (callback_t<int> callback) {
    std::packaged_task<int/*How to not write int but derive the type from callback*/()> task {
        [] () {return 42;}
    };

    task();
    callback(task.get_future());
}

int main()
{
    callback_t<int> c {[] (auto i) {
        std::cout << i.get() << "\n";
    }};
    foo (c);
}

The following:

template<class T> struct get_first_argument_type {};
template<class R, class Arg>
struct get_first_argument_type<std::function<R(Arg)>> {
    using argument_type = Arg;
};

template<typename T>
void foo(callback_t<T> callback) {
    using the_future = typename get_first_argument_type<callback_t<T>>::argument_type;
    // https://stackoverflow.com/questions/26435084/how-to-get-the-return-type-of-a-member-function-from-within-a-class
    using your_type = typename std::result_of<decltype(&the_future::get)(the_future)>::type;
    static_assert(std::is_same<your_type, int>::value, "");
}

works.

In foo(callback_t<int>) , there's no need for

How to not write int but derive the type from callback

because you know int is the parameter, it's right there.

If foo were a template, it would also be simple

template <typename T>
void foo (callback_t<T> callback) {
    std::packaged_task<T()> task {
        [] () {return 42;}
    };

    task();
    callback(task.get_future());
}

If you really insist on extracting it, you can write a trait.

template <typename>
struct callback_arg;

template <typename T>
struct callback_arg<callback_t<T>> { using type = T; };

template <typename T>
using callback_arg_t = typename callback_arg<T>::type;

And use it like

using int_callback = std::function<void(std::future<int>)>;

void foo (int_callback callback) {
    std::packaged_task<callback_arg_t<int_callback>()> task {
        [] () {return 42;}
    };

    task();
    callback(task.get_future());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM