12

I am passing a pointer to function into a function template:

int f(int a) { return a+1; }

template<typename F>
void use(F f) {
    static_assert(std::is_function<F>::value, "Function required"); 
}

int main() {
    use(&f); // Plain f does not work either.
}

But the template argument F is not recognized by is_function to be a function and the static assertion fails. Compiler error message says that F is int(*)(int) which is a pointer to function. Why does it behave like that? How can I recognize the function or pointer to function in this case?

Juraj Blaho
  • 13,301
  • 7
  • 50
  • 96

1 Answers1

15

F is a pointer to function (regardless of whether you pass f or &f). So remove the pointer:

std::is_function<typename std::remove_pointer<F>::type>::value

(Ironically, std::is_function<std::function<FT>> == false ;-))

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 2
    I loathe implicit conversions :( – Matthieu M. May 06 '13 at 09:33
  • 5
    *"(Ironically, `std::is_function> == false` ;-))"* - Maybe for future standards a `std::is_callable` might be a good idea, since `std::is_function` doesn't even work for lambdas, just simple functions (and the times each callable was a function are way over in modern C++). – Christian Rau May 06 '13 at 11:30
  • 1
    @ChristianRau `std::is_function` is one of the primary classification traits. `is_callable` or anything like that would serve a completely different purpose altogether. – Luc Danton May 06 '13 at 16:08
  • @LucDanton Yes, of course. Nobody argues that `std::is_function` has its value and fits perfectly to things like `std::is_array` (which should *not* return true for `std::array` either) or `std::is_class`. But nevertheless an *additional* `std::is_callable` would be a nice idea and would be in line with other rather high-level traits, like (the AFAIK already proposed) `std::is_swappable` and the desperately needed (though AFAIK not proposed) `std::is_hashable`. – Christian Rau May 06 '13 at 16:16