Search code examples
c++templatesc++14sfinaeenable-if

passing return value of a called method throug std::enable_if_t


I have a template method, that executes a base class method of the object with a fixed value of arguments if it exists,a and doesn't if not exists, and it works. I was using sfinae with std::enable_if_t to resolve if a method exists.

The thing that I don't get is - how I can pass-through the actual return value of the calling method, beyond std::enable_if_t.

This is how my code looks:

#define PREPARE_BASE_METHOD_W_2ARGS_CALL_HELPERS(METHOD_NAME, ARG1, ARG2) \
namespace detail{ \
  template <typename T, typename A1, typename A2> static auto test_##METHOD_NAME(int) -> sfinae_true<decltype(std::declval<T>().METHOD_NAME(std::declval<A1>(), std::declval<A2>()))>; \
  template <typename  , typename A1, typename A2> static auto test_##METHOD_NAME(long) -> std::false_type; \
  template <typename T, typename A1, typename A2> struct has_##METHOD_NAME : decltype(detail::test_##METHOD_NAME<T, A1, A2>(0)){}; \
  template <typename Base, typename T> auto call_##METHOD_NAME##_if_any(T& obj, ARG1 arg1, ARG2 arg2) -> std::enable_if_t<has_##METHOD_NAME<Base,ARG1,ARG2>::value, bool> { \
      obj.Base::METHOD_NAME(arg1, arg2); \
      return true; \
  } \
  template <typename Base, typename T> auto call_##METHOD_NAME##_if_any(T& obj, ARG1, ARG2) -> std::enable_if_t<!has_##METHOD_NAME<Base,ARG1,ARG2>::value, bool> { return false; } \
} \

Yes, it is a macro, but I hope there will be no problem understanding whats going on. Where and I how I can return the result of obj.Base::METHOD_NAME(arg1, arg2) from call_##METHOD_NAME##_if_any(..)? I am confused, because I think, that the return here is already occupied by sfinae logic.


Solution

  • It's very simple, just put the std::enable_if_t in the template-params-list with a default arg, e.g.

    template <typename Base, typename T, std::enable_if_t</*Your condition here*/, bool> = true>
    

    Then you can use decltype(auto) for the actual return type.