检测模板化函数是否接受具有特定签名的回调

时间:2017-02-03 04:54:25

标签: c++ templates c++14 metaprogramming sfinae

目前我正在尝试使用sfinae创建一个静态检查,它会检查回调函数(考虑[](auto&& callback) { callback(tag1{}); })是否接受带有特定签名的回调:

#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)

但似乎continuation(callback)的评价并没有使用SFINAE,因为clang报告错误:

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

还有其他可能使上面的检查有效吗?

注意:即使我们根据回调([](auto&& callback) { return callback(tag1{}); })设置延续的返回类型,它也不起作用。

0 个答案:

没有答案