让我们假设我们有n个变量的函数
y = f (x1, ..., xn)
这个函数我想作为一个参数传递。
在Matlab中,可以使用以下构造:
function y=func(x)
y = sin(x(0)) * cos(x(1)) //Any definition, not important
p_func=@func; //Define handle
可以将句柄用作另一个函数的参数:
y = function2(p_func, n);
其中n代表维度......
如何使用C ++重写此代码?我们使用带有函数模板的简单模型
temmplate <typename T>
T func( const T *arg, const short n) {return sin(arg[0]) * cos(arg[1])};
其中xi参数由n个元素的1维数组表示。问题是在这种情况下,不可能使用指向函数模板的指针
template <class T>
static T ( *pfunc ) ( const T *arg, const short n )
只有专业化......也许另一种模式可能更合适......感谢您的帮助...
注: 我知道类模板很有用
template <typename T>
class Foo
{
T func( const T *args, const short n);
};
这项建设有效:
template <class T>
static T ( *pfunc ) ( const T *arg, const short n )
但它可能不会在库的当前模型中使用(我不能影响它)。
答案 0 :(得分:3)
C ++是一种静态类型语言。 C ++中的每个对象,无论是函数指针还是其他任何对象,都必须具有特定类型。函数指针的类型基于要指向的函数的参数类型。
模板不是对象,因此您无法获取指向模板的指针。您可以获得指向模板的实例化的指针。使用func
定义,func<int>
是一个需要const int*
和short
的函数。您可以获得指向func<int>
的指针。但是func
是一个模板;你无法获得指向模板的指针。
这就是为什么C ++程序经常抛出函数而不是函数指针。函子可以有一个模板operator()
方法,因此您可以像调用模板函数一样调用它们。但是既然你说你必须使用函数指针,那就没有什么可以做的了。
答案 1 :(得分:1)
我不认为这在C ++中很容易解决,但是有类似案例的方法。你应该看一下boost::bind and boost::function库。它是为了解决在C ++中传递函数指针的令人讨厌的细节(并且它们也允许传递类方法)。据我所知,他们并没有真正使用通用N,而是为任意N个参数实例化模板。如果你想得到类似的东西,那绝对值得一看。
答案 2 :(得分:1)
问题不在于“n”。问题是模板化类型T.
您是否尝试声明一个变量(类型指针指向函数),这里?
template <class T>
static T ( *pfunc ) ( const T *arg, const short n )
如果没有实例化模板,这将无效。
这是因为否则,类型检查是不可能的。在初始化指针时,类型检查器无法检查T是否与取消引用它时相同。
您可能需要查看更大的背景。你想在哪里使用那个声明?将模板参数移动到该上下文。
例如,您可以使用模板参数T的函数或类。 在那里,您可以声明,初始化和取消引用任何在其类型中包含T的函数指针。
也许您可以在分配函数指针的位置“绑定”参数。因此,结果函数将是一个无效函数,您可以在不知道参数类型的情况下使用它。
答案 3 :(得分:1)
你无法获得指向模板函数的指针,因为模板不是一个对象,它只是编译时语法构造产生多个特定函数 - 模板实例化。模板实例化,例如f<int>(const int*, short)
是对象,可以指向。
如果您只是想要一些简单而统一的方法从模板实例化中获取函数指针,请使用declspec()
(我假设您使用的是现代C ++ 11兼容编译器):
template <class T> static T f(const T *, const short )
{
// Implementation
...
}
// Declaring function pointers for int & double
typedef decltype(&f<int>) IntFuncPtr;
typedef decltype(&f<double>) DoubleFuncPtr;
// Sample usage
IntFuncPtr intFunc = &f<int>;
intFunc(NULL, 0);
DoubleFuncPtr doubleFunc = &f<double>;
doubleFunc(NULL, 0);