问题
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:
- Sets the return type of
foo
would have the same return type asbar
- Ensures that
bar
is a function that accepts an argument of typeT
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?
回答1:
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.
来源:https://stackoverflow.com/questions/54947367/is-there-a-declval-for-function-pointers