Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a function is callable

I am using the is_callable structure defined as follows

template <typename F, typename... Args>
struct is_callable {
  template <typename U>
  static auto test(U* p) -> decltype((*p)(std::declval<Args>()...), void(), std::true_type());

  template <typename U>
  static auto test(...) -> decltype(std::false_type());

  static constexpr bool value = decltype(test<F>(nullptr))::value;
};

I am using this to test a lambda declared as:

template <typename T>
struct runner {
  T t;

  template <typename F, typename = typename std::enable_if<is_callable<F, T&>::value || is_callable<F, T&&>::value>::type>
  void run(F&& f) { 
    return f(t); 
  }
};

runner<int> a{0};
a.run([&] (auto& x) {
  x++;
});

Why does this fail compilation on the enable_if on AppleClang? Shouldn't the autos get deduced correctly?

like image 441
ssb Avatar asked Nov 07 '22 19:11

ssb


1 Answers

Your case for the true_type test looks wrong. At any rate, your code is more complicated than it needs to be. Try the following minimal working example:

#include <utility>

template<typename F, typename...Args> struct is_callable {
  template<typename F2, typename...Args2> static constexpr std::true_type
  test(decltype(std::declval<F2>()(std::declval<Args2>()...)) *) { return {}; }

  template<typename F2, typename...Args2> static constexpr std::false_type
  test(...) { return {}; }

  static constexpr bool value = decltype(test<F, Args...>(nullptr))::value;
};

void f0();
static_assert(is_callable<decltype(f0)>::value, "f0()");
static_assert(!is_callable<decltype(f0), int>::value, "f0(0)");

int f1(int);
static_assert(!is_callable<decltype(f1)>::value, "f1()");
static_assert(is_callable<decltype(f1), int>::value, "f1(0)");
static_assert(!is_callable<decltype(f1), int, int>::value, "f1(0, 0)");

auto __attribute__((unused)) f2 = [](int, char *) { return 7; };
static_assert(is_callable<decltype(f2), int, char *>::value, "f2(int, char *)");
static_assert(!is_callable<decltype(f2), int, int>::value, "f2(int, int)");
like image 176
user3188445 Avatar answered Nov 13 '22 04:11

user3188445