1

Currently I'm trying to create a statical check using sfinae which checks whether a callback taking function (consider [](auto&& callback) { callback(tag1{}); }) is accepting a callback with a certain signature:

#include <tuple>
#include <type_traits>

template <typename... Args> struct acceptor {
  void operator()(Args...) const {}
};

template <typename T, typename Args, typename = std::void_t<>>
struct testit : std::false_type {};

template <typename T, typename... Args>
struct testit<T, std::tuple<Args...>,
              std::void_t<decltype(std::declval<T>()(acceptor<Args...>{}))>>
//                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Try to invoke the continuation with a callback of the given signature                    
    : std::true_type {};

struct tag1 {};
struct tag2 {};

int example() {
  auto continuation = [](auto&& callback) { callback(tag1{}); };

  std::true_type accept = testit<decltype(continuation), std::tuple<tag1>>{};

  std::false_type doesnt_accept = testit<decltype(continuation), std::tuple<tag2>>{};
  return 0;
}

Demo (GCC Explorer)

But it seems like that the evaluation of continuation(callback) doesn't make use of SFINAE since clang reports an error:

<source>:21:45: error: no matching function for call to object of type 'acceptor<tag2>'
auto continuation = [](auto&& callback) { callback(tag1{}); };

Is there any other possibility to make the check above work?

Note: Even when we make the return type of the continuation dependent on the callback ([](auto&& callback) { return callback(tag1{}); }) it doesn't work.

Naios
  • 1,513
  • 1
  • 12
  • 26
  • You can't really do that. `continuation` is callable with literally anything. You'll have to declare its argument with explicit type: `acceptor callback` for that to work. Do you actually want to check if `callback` is callable with specified arguments? – yuri kilochek Feb 03 '17 at 05:31
  • I don't see any reason why it's different from normal class member detection. I'm sure that I want to check whether a callback is callable with specific arguments from the contnuation. The reason why I want to do this is that I've got a known callback signature and several continuations are chained together with an `and` logic. The calllback is finally invoked with the result of all continuations composed together. This means we must know which continuations will yield which result in order to provide tuples for storage caching although we can't infer that from it's signature. – Naios Feb 03 '17 at 05:46
  • 1
    The problem is that you are trying to sfinae on expression within function body. Substitution failure there is always a hard error. – yuri kilochek Feb 03 '17 at 06:58
  • All right thanks, it's described in http://stackoverflow.com/questions/27301135/does-sfinae-apply-to-function-bodies. If you want you may add your comment as answer. – Naios Feb 03 '17 at 08:23

0 Answers0