出于数学目的,我想编写一个通用仿函数类来包含带有变量和参数的简单数学方程。想象一下简单的抛物线:
y=f(x;a,b,c)=a*x*x+b*x+c
此处a
,b
和c
是为一个抛物线设置一次的参数。那么
纵坐标值y
是通过提供某些值来计算的
变量x
。我用variadic编写了一个简单的gen_func
类
模板与std::tuple
组合用于保存参数和a
变量的可变参数包。这堂课的骨架是
发现于How to store variadic template arguments?
我是新c ++ 11标准的新手,我知道写得正确 使用可变参数模板的代码是一件非常复杂的事情。
出于某些目的,我想通过 call-by-reference 来更改变量。但在这里,编译器(gcc 4.7)确实抱怨。为简单起见,我通过简单的功能更改测试了代码。它的唯一目的是改变传递的第一个变量的值。这是一个简单程序的代码:
#include <tuple>
#include <iostream>
#include <functional>
#include<utility>
using namespace std;
// Compile with : g++ -o X.bin -Wall -pedantic -std=c++11 X.cpp
// Stuff for compile-time recursive parameter pack expansion:
namespace generic
{
template <std::size_t... Ts>
struct index_sequence {};
template <std::size_t N, std::size_t... Ts>
struct sequence_generator : sequence_generator<N - 1, N - 1, Ts...> {};
template <std::size_t... Ts>
struct sequence_generator<0, Ts...> : index_sequence<Ts...> {};
template< typename ReturnType , typename... Args > using generic_function_pointer = ReturnType (*) ( Args... args ) ;
}
// The generic Function wrapper:
template < typename R , class F , typename... Ps>
class gen_func
{
public:
// Constructor
gen_func(F&& f,Ps&&...parms){
func = forward<F>(f);
parameters=make_tuple(forward<Ps>(parms)...);
}
// execute-Function for public call:
template<typename... Vars>
R execute(Vars&&... vars) {
return f_decon<Vars... , Ps...>( forward<Vars>(vars)... , parameters );
}
//
private:
// "Deconvolution Function"
template<typename... Vars , typename... Ts >
R f_decon( Vars&&... vars , tuple<Ts...>& tup ){
return f_proxy<Vars...,Ps...>( forward<Vars>(vars)... , tup , generic::sequence_generator<sizeof...(Ts)>{} );
}
// "Proxy-Function" calling the wrapped Function func:
template<typename... Vars , typename... Ts , size_t... Is>
R f_proxy( Vars&&... vars , tuple<Ts...>& tup , generic::index_sequence<Is...> ){
return func( forward<Vars>(vars)... , get<Is>(tup)... );
}
// The wrapped Function f
F func;
// The tuple holding optional parameters for function f:
tuple<Ps...> parameters;
};
// Partial template Specialization of gen_func for Functions with Return Type void:
template <class F , typename... Ps>
class gen_func<void,F,Ps...>
{
public:
// Constructor
gen_func(F&& f,Ps&&...parms){
func = forward<F>(f);
parameters=make_tuple(forward<Ps>(parms)...);
}
// execute-Function for public call:
template<typename... Vars>
void execute(Vars&&... vars) {
f_decon<Vars... , Ps...>( forward<Vars>(vars)... , parameters ); // Line 75
}
//
private:
// The wrapped Function f
F func;
// The tuple holding optional parameters for function f:
tuple<Ps...> parameters;
// "Deconvolution Function"
template<typename... Vars , typename... Ts >
void f_decon( Vars&&... vars , tuple<Ts...>& tup ){ // Line 85
f_proxy<Vars...,Ts...>( forward<Vars>(vars)... , tup , generic::sequence_generator<sizeof...(Ts)>{} );
}
// "Proxy-Function" calling the wrapped Function func:
template<typename... Vars , typename... Ts , size_t... Is>
void f_proxy( Vars&&... vars , tuple<Ts...>& tup , generic::index_sequence<Is...> ){
func( forward<Vars>(vars)... , get<Is>(tup)... );
}
};
void change(int& m,int n){
cout << "Changing!" << endl;
int res=42+n;
m=res;
}
int main()
{
typedef generic::generic_function_pointer<void,int&,int> chg_ptr;
gen_func<void,chg_ptr> y(change);
// The Variable to be altered by change
int j=0;
cout << "j='" << j << "'" << endl; // should be 0
// Wrapped Function call:
y.execute(j,21); // Line 113
cout << "j='" << j << "'" << endl; // should be 63
return 0;
}
编译器确实抱怨:
X.cpp: In instantiation of ‘void gen_func<void, F, Ps ...>::execute(Vars&& ...) [with Vars = {int&, int}; F = void (*)(int&, int); Ps = {}]’:
X.cpp:113:15: required from here
X.cpp:75:12: error: no matching function for call to ‘gen_func<void, void (*)(int&, int)>::f_decon(int&, int, std::tuple<>&)’
X.cpp:75:12: note: candidate is:
X.cpp:85:14: note: template<class ... Vars, class ... Ts> void gen_func<void, F, Ps ...>::f_decon(Vars&& ..., std::tuple<_Args2 ...>&) [with Vars = {Vars ...}; Ts = {Ts ...}; F = void (*)(int&, int); Ps = {}]
X.cpp:85:14: note: template argument deduction/substitution failed:
X.cpp:75:12: note: mismatched types ‘std::tuple<_Elements ...>’ and ‘int’
似乎通过引用传递变量x
来使代码错误,以便可以通过包装函数更改来更改它。我的计划方法完全错了吗?纠正是否简单?有没有更好的方法来实现我的目标?提前感谢任何建议!