3

I have a function that wraps another call with exception handling. Most invocation doesn't return anything (void) but for some invocation the function may return an int or the like. This works fine except Im left struggling with the default return val or return void.

Im currently looking at something like the following

template<class T> struct member_function_trait;
template<class T, class R> struct member_function_trait<R T::*> { using type = T; using ret = R; };



template<auto f, class T, typename... Args>
auto DispatchImpl(T* obj, Args&&... args) {
  try {
    return (static_cast<typename member_function_trait<decltype(f)>::type*>(obj)->*f)(std::forward<Args>(args)...);
  }
  catch (std::runtime_error& e) {
    //handled exception
  }
  return member_function_trait<decltype(f)>::ret; //<--- how to return default constructed or 'void' here ?
}

Compile error:

error C2275: 'member_function_trait<void (__cdecl MyClass::* )(void)>::ret': illegal use of this type as an expression

Im stuck as to how to proceed with the issue. Is there some simpel trick Im overlooking ? (I hope so)

darune
  • 10,480
  • 2
  • 24
  • 62

1 Answers1

4

First off, your trait is not quite correct, because ret will be the function type, not its return type. You probably meant this:

template<class T, class R, class... A>
struct member_function_trait<R (T::*)(A...)>
{
  using type = T;
  using ret = R;
};

After this, just creating ret() will give you precisely what you want:

// In DispatchImpl:
return typename member_function_trait<decltype(f)>::ret();

[Live example]

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • When I try that I get "error C2672: 'default_constructed': no matching overloaded function found" – darune Sep 12 '19 at 07:52
  • @darune Because your trait is wrong; answer edited. – Angew is no longer proud of SO Sep 12 '19 at 07:52
  • Why `default_constructed`? Is is not needed. `return void();` is a perfectly valid expression. – geza Sep 12 '19 at 07:57
  • Yeah, `default_constructed` isn't needed unless you wan't/need brace-init – darune Sep 12 '19 at 07:59
  • @darune: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1114r0.html#2351 This is fixed in the standard, but no major compiler implemented the fix yet. – geza Sep 12 '19 at 08:07
  • Issue is that we need all traits variant (combination of cv qualifier, ref qualifier, noexcept, C-ellipsis). `using Ret = decltype(static_cast::type*>(obj)->*f)(std::forward(args)...));` with `return Ret();` might be simpler if traits is not reused. – Jarod42 Sep 12 '19 at 08:49