Reputation: 24039
I'm trying to deduce the return type of a callable type, i.e. a function pointer or a functor.
I previously asked and got an answer showing how to do this for function pointers with hints for how to do this for functors.
Function return type deduction in C++03
Based on that, I have this helper struct which now works for functors but no longer works for function pointers.
// functors
template<class T>
struct Return;
{
typedef typename T::result_type type;
};
// function pointers
template<class R>
struct Return<R (*)()>
{
typedef R type;
};
This works for cooperating functors that provide a result_type
typedef but not for function pointers. clang gives the following:
error: type 'int (*)(int)' cannot be used prior to '::' because it has no members
typedef typename T::result_type type;
I'm confused by why this isn't a SFINAE error that would move on and catch the specialization of Return
.
You can try this yourself and also see some of the context to what I'm doing.
http://coliru.stacked-crooked.com/a/53f4c8c90787e329
Context
This builds on this question.
“Overload” function template based on function object operator() signature in C++98
In that question I was trying to create a function template that will map a std::vector to a new std::vector by using a passed mapping function. Now I'm trying to map from a container that provides a means of iterating over its contents. In the answer to that question the function template had the form:
template<typename F, typename T>
typename expr_check<sizeof(declval<F>()(declval<T>())), std::vector<T> >::type
map_vec(F fnc, const std::vector<T>& source)
Where F
is a callable type and T
is both the type of the argument taken by type F
and also parameterizes the return type, std::vector<T>
. See the question for explanation of declval
.
Now I want the function template to take a container type, call it C
. My thinking is that T should be deduced as the return type of type F
here and so is no longer a parameter itself. Right now I'm trying to get the template to work with this signature:
template<typename F, typename C>
typename expr_check<sizeof(declval<F>()(declval<int>())),
std::vector<typename Return<F>::type> >::type
map_vec(F fnc, const C& source);
Upvotes: 4
Views: 1806
Reputation: 45654
Your error is only specializing for exactly zero arguments.
As pre-C++11 does not have variadic templates, you will have to add one specialization for each count up to your limit.
If you can use C++11 features, just use std::result_of
.
Upvotes: 3
Reputation: 24039
This was a silly mistake that Deduplicator caught.
The working example:
http://coliru.stacked-crooked.com/a/cdb79bbdeedfaa65
The problem was simply that there need to be specializations of Return
appropriate for the function signatures that will be used.
// functors
template<class T>
struct Return
{
typedef typename T::result_type type;
};
// function pointers
template<class R, class T>
struct Return<R (*)(T)>
{
typedef R type;
};
// function pointers
template<class R, class T, class U>
struct Return<R (*)(T, U)>
{
typedef R type;
};
Upvotes: 2