Универсальная оболочка для возврата последнего параметра функции в C ++ - PullRequest
2 голосов
/ 18 октября 2011

Мы написали большую библиотеку функций, прототипы которых в основном выглядят так:

void my_fun(
  const in_class & in_param_1, 
  const in_class & in_param_2,
  const in_class & in_param_3,
  out_class & out_param);

Есть ли общий способ обернуть эти функции так, чтобы следующее было эквивалентным (предполагая, что out_param записывается только в my_fun):

out_class my_out;
my_fun(my_in1,my_in2,my_in3,my_out);

и

out_class my_out = generic_wrapper(&my_fun,my_in1,my_in2,my_in3);

Как можно написать такой generic_wrapper?Если это возможно, можно также записать его так, чтобы число входных параметров было переменным, поэтому я мог бы использовать его, скажем, с my_fun2, который, возможно, занимает 4 in_param_'s?

Ответы [ 3 ]

3 голосов
/ 18 октября 2011

Рассмотрим все случаи:

template<class T1, class Out>
Out generic_wrapper(void (*f)(const T1 &, Out &), const T1 & t1) { 
    Out out; 
    f(t1,out); 
    return out;
}

template<class T1, class T2, class Out>
Out generic_wrapper(void (*f)(const T1 &, const T2 &, Out &), const T1 & t1, const T1 & t2) { 
    Out out; 
    f(t1,t2,out); 
    return out;
}

// .....

template<class T1, class T2, class T3, class T4, class T5, class Out>
Out generic_wrapper(void (*f)(const T1 &, const T2 &, const T3 &, const T4 &, const T5 &, Out &), const T1 & t1, const T1 & t2, const T3 & t3, const T4 & t4, const T5 & t5) { 
    Out out; 
    f(t1,t2,t3,t4,t5,out); 
    return out;
}
1 голос
/ 18 октября 2011

С помощью шаблонов с переменным кодом C ++ 11 можно было бы реализовать обертку следующим образом:

template <class Func, class ...Args>
typename last_argument_type<Func>::type wrapper(Func f, Args&& ...args)
{
    typename last_argument_type<Func>::type result;
    f(std::forward<Args>(args)..., result);
    return result;
}

, и я реализовал last_argument_type как:

//typedefs last type in T... as type
template <class ...T>
struct last_type;

template <class T, class ...U>
struct last_type<T, U...> { typedef typename last_type<U...>::type type; };

template <class T>
struct last_type<T> { typedef T type; };

//typedefs the type of the last argument of a function as type
//removes reference 
//e.g void(int, float, double&) -> type = double
template <class ...Args>
struct last_argument_type;

template <class Ret, class ...Args>
struct last_argument_type<Ret(*)(Args...)> {
    typedef typename std::remove_reference<typename last_type<Args...>::type>::type type;
};

Fullпример на http://ideone.com/ef3zD

0 голосов
/ 18 октября 2011

В C ++ 0x мы также можем попытаться использовать шаблон с переменными значениями:

template <class Out, class... Ins>
Out generic_wrapper(void (*fun)(const Ins&... , Out&), const Ins&... ins)
{
    Out out;
    fun(ins..., out);
    return out;
}

, но я не могу использовать его без явного указания аргументов шаблона (GCC 4.6.1):

int main()
{
    in_class in;
    out_class out1a = generic_wrapper(my_fun_1, in); // fails to compile...
    out_class out1b = generic_wrapper<out_class, in_class>(my_fun_1, in); // works...
    return 0;
}
...