Search code examples
c++templatesc++17template-meta-programminginvoke-result

Return default constructed or void from template function


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)


Solution

  • 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]