1

I have a function and I need to test whether I can pass an argument of a given type to it. For example:

template<typename T, auto F>
decltype(F(declval<T>{})) foo();

Calling foo<int, bar>() does 2 things:

  1. Sets the return type of foo would have the same return type as bar
  2. Ensures that bar is a function that accepts an argument of type T

Unfortunately I don't have access to auto template types, but I still want to accomplish both of these. What I need is a decltype for function pointers, which would allow me to do something like this:

template <typename T, typename F>
decltype(declval<F>(declval<T>{})) foo();

So I could still call foo<int, bar>() and get the same result. Of course there isn't a declval for function pointers. But is there another way I could accomplish this?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

1 Answers1

3

Of course there isn't a declval for function pointers.

What do you mean? std::declval works perfectly with function pointer types:

template<typename F, typename... Args>
using call_t = decltype(std::declval<F>()(std::declval<Args>()...));

In this example, F can be a function pointer type, a lambda type or any callable types.

Here's an example of usage:

template<typename T, typename F>
auto foo() -> call_t<F, T>;

Another example using the detection idiom (implementable in C++11):

template<typename F, typename... Args>
using is_callable = is_detected<call_t, F, Args...>;

static_assert(is_callable<void(*)(int), int>::value, "callable")

Note that all this can be replaced by std::invoke_result_t and std::is_invocable in C++17. I'd suggest mimicking those to have the most seamless upgrade.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • The problem with this is the OP doesn't have an actual function pointer to use in the function. They still have to get that in there somehow. – NathanOliver Mar 01 '19 at 15:24
  • If I look at it's two requirements, he don't need the actual function pointer value – Guillaume Racicot Mar 01 '19 at 15:25
  • Looks like you're right. Not sure why the OP thinks it doesn't work. – NathanOliver Mar 01 '19 at 15:41
  • @NathanOliver This has my +1 it does work just not for me in Visual Studio, but I tested in g++ and that does work. I'll post a follow up question... Also if no one can give me a cross platform solution I will accept this. – Jonathan Mee Mar 01 '19 at 16:35
  • @JonathanMee can you create a compiler explorer example that reproduce your error? This code should be cross platform. – Guillaume Racicot Mar 01 '19 at 16:40
  • @NathanOliver So my example is a little more involved. I think the problem is nesting `using` statements on VisualStudio: https://stackoverflow.com/q/54949124/2642059 – Jonathan Mee Mar 01 '19 at 16:57
  • @GuillaumeRacicot You're right this is an excellent answer and _should_ be cross platform... but for VisualStudio bugs. – Jonathan Mee Mar 01 '19 at 16:57