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;
}
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.