简体   繁体   中英

Deducing a function pointer return type

I think code will better illustrate my need:

template <typename F>
struct return_type
{
  typedef ??? type;
};

so that:

return_type<int(*)()>::type -> int
return_type<void(*)(int,int)>::type -> void

I know of decltype and result_of but they need to have arguments passed. I want to deduce the return type of a function pointer from a single template parameter. I cannot add the return type as a parameter, because that's exactly what I want to hide here...

I know there's a solution in boost, but I can't use it, and an attempt to dig it out from boost resulted in a spectacular failure (as it often does).

C++11 solutions welcome (as long as supported in VS2012).

If you can use variadic templates (November '12 CTP), this should work:

template <class F>
struct return_type;

template <class R, class... A>
struct return_type<R (*)(A...)>
{
  typedef R type;
};

Live example .

If you can't use variadic templates, you'll have to provide specific specialisations for 0, 1, 2, ... parameters (by hand or preprocessor-generated).

EDIT

As pointed out in the comments, if you want to work with variadic functions as well, you'll have to add one extra partial specialisation (or one for each parameter count in the no-variadic-templates case):

template <class R, class... A>
struct return_type<R (*)(A..., ...)>
{
  typedef R type;
};

It has been a while since the question has been asked. For C++17, there is an interesting option. However, the syntax is a bit different from what was originally asked, but the result (a type) is the same.

First, we need a helper function. As you see here, the function accepts a function pointer and returns an object of type R. We need this only for a decltype statement and therefore this function will never be called, so a forward declaration is sufficient.

template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...));  // forward declaration only for decltype

The trick is to provide the function pointer as a template auto parameter, which is forwarded to a decltype statement:

template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));

Now it is easy to get the return type:

#include <iostream>
#include <type_traits>

template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...));  // forward declaration only for decltype

template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));

int func1(char c, int i, long l);  // also here only forward declarations needed
void func2(unsigned u, float f);
double func3(bool b);

int main()
{
    std::cout << std::is_same_v<int, ReturnType<func1>> << std::endl;
    std::cout << std::is_same_v<void, ReturnType<func2>> << std::endl;
    std::cout << std::is_same_v<double, ReturnType<func3>> << std::endl;
    std::cout << std::is_same_v<void, ReturnType<func1>> << std::endl;
}

You can try the complete example in Wandbox: https://wandbox.org/permlink/5akL0MQDoDuJlQNY

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM