vendredi 23 septembre 2016

How to convert std::result_of to decltype in a template argument

Consider the following code. Is there any way to change std::result_of<F()>::type to use decltype instead?

Or is this one of those situations where it's better to leave result_of alone?

#include <iostream>
#include <future>
#include <type_traits>

template<typename T>
struct NopErrCB
{
  constexpr T operator() () const { return T(); }
};

template <typename Func, typename ErrCB>
struct SafeTaskWrapper {
  Func f;
  ErrCB errCB;

  template <typename... T>
  auto operator()(T&&... args) -> decltype(f(args...)) {
    try
    {
      return f(std::forward<T>(args)...);
    }
    catch (...)
    {
      return errCB();
    }
  }

};
//                                   vvv OVER HERE  vvv
template <typename F>
SafeTaskWrapper<F, NopErrCB<typename std::result_of<F()>::type>> make_safe_task(F&& f) {
  return { std::forward<F>(f) };
}

template <typename F, typename ErrCB>
SafeTaskWrapper<F, ErrCB> make_safe_task(F&& f, ErrCB&& cb) {
  return { std::forward<F>(f), std::forward<ErrCB>(cb) };
}

int main() {
  auto futA = std::async(std::launch::async, make_safe_task([] { throw "A"; return 1; }));
  auto futB = std::async(std::launch::async, make_safe_task([] { throw "B"; return 1; }, [] { return 2; }));
  auto futC = std::async(std::launch::async, make_safe_task([] { throw "C"; }));
  std::cout << futA.get() << std::endl;
  std::cout << futB.get() << std::endl;
  futC.get();
}

PS. Please don't mind the purpose of the SafeTaskWrapper. I know a future already handles C++ exceptions. This is just a demo, the actual code is for handling Windows SEH exceptions, but that doesn't matter for this question.

Aucun commentaire:

Enregistrer un commentaire