简体   繁体   中英

Get type of function first parameter for template function return type

I have the following template function:

template<class T, class F> T function(F& f) {
        ...
        T t; 
        f(t);
        return t;
}

It's expected to be used with F with the form

void some_function(SomeType& s);

in this way

function<SomeType>(some_function);

The first template argument seems redundant because can be deduced from the parameters of the parameter function. The question is Exists a way to get rid of the first template parameter?

Something like

template<class F> first_param_type<F> function(F& f) {
        ...
        first_param_type<F> t; 
        f(t);
        return t;
}

So that I can use it as

function(some_function);
template<class T>
T function( void(*f)(T&) ) {
  ...
  T t; 
  f(t);
  return t;
}

solves the problem as stated. The general problem cannot be solved (where F is an arbitrary callable), as callables in C++ can accept more than one type, and deducing what types are acceptable cannot be solved in the general case.

If you had a list of types you support, it an be solved in general.

The basic problem in C++14 is function([](auto&x){ std::cout << x << '\\n'; }) . The same problem exists in C++11 with function objects with a template operator() . The fact that auto-lambdas are supported in C++14 means that such objects are going to become more and more common in the future.

Consider changing your design so that the signature of your F is T() rather than void(T&) . Then we get:

template<class F>
std::result_of_t<F()>
function( F&& f ) {
  ...
  return std::forward<F>(f)();
}

or typename std::result_of<F()>::type in C++11.

I hope I understood your question, maybe I am wrong...

First of all I expect your template function must be called and for the call it needs additional parameters which I could not found in your example code.

But ok, what I expect what you can do:

#include <iostream>
using namespace std;

template <typename RetType, typename ... Parms>
auto TemplateFunction  ( RetType(*ptr)(Parms ...), Parms ... parms ) -> RetType
{   
    RetType ret;
    ret = (*ptr)( parms...);
    cout << "Value ret in Wrapper is:" << ret << endl;
    return ret;
}   

double AnyFunc(int a, int b) { return 3.14 * a + b; }
std::string OtherFunc(  ) { return "Hallo"; } 

int main()
{   
    double result = TemplateFunction(&AnyFunc, 1,3);

    cout << "Result is " << result << endl;

    cout << TemplateFunction(&OtherFunc) << endl;
}   

As you already mentioned, there is no need to give the return type as additional parameter, because it can be found in the given as type in the presented function pointer to the template.

The wrapper template will work for all return types but not for void !

UPDATE

I absolutely agree with Yakk's answer I just wanted to mention an other but very similar way:

#include <functional>

template < class Type >
Type myFunction( const std::function< void( Type& ) >& aFunction )
{
    Type instance;
    aFunction( instance );
    return instance;
}

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