C++ 将函数指针用作模板方法的默认参数时出错
尝试编译此代码时,在Visual Studio 2012中出现以下编译器错误:C++ 将函数指针用作模板方法的默认参数时出错,c++,templates,namespaces,function-pointers,default-arguments,C++,Templates,Namespaces,Function Pointers,Default Arguments,尝试编译此代码时,在Visual Studio 2012中出现以下编译器错误: error C2440: 'default argument' : cannot convert 'void(_cdecl*)(void)' to 'void(_cdecl*)(void)' 我的代码: namespace bar { template<typename T> void foo(); template<> void foo<int>() {} }
error C2440: 'default argument' : cannot convert 'void(_cdecl*)(void)' to 'void(_cdecl*)(void)'
我的代码:
namespace bar {
template<typename T> void foo();
template<> void foo<int>() {}
}
struct A {
void(*f)();
template<typename T> inline void set_func(void(*f)()=bar::foo<T>) {this->f=f;}
};
int main(void) {
A a;
a.set_func<int>();
return 0;
}
名称空间栏{
模板void foo();
模板void foo(){}
}
结构A{
无效(*f)();
模板内联void set_func(void(*f)(=bar::foo){this->f=f;}
};
内部主(空){
A A;
a、 set_func();
返回0;
}
当我将bar::foo
移动到全局名称空间中时,我不再得到错误。谁能解释一下吗
我编辑了上面的代码,以消除对成员函数和模板专门化的一些混淆。我还删除了typedef,它给出了相同错误的更奇怪的版本:
无法将'void(_cdecl*)(void)'转换为'void(_cdecl*)(void)
,因为这显然是编译器本身的一个bug,所以我所能做的就是创建一个解决方案来实现相同的效果
我删除了默认参数并使用了重载方法,如下所示:
template<typename T> inline void set_func() {this->f=bar::foo<T>;}
template<typename T> inline void set_func(void(*f)()) {this->f=f;}
template inline void set_func(){this->f=bar::foo;}
模板内联void set_func(void(*f)(){this->f=f;}
此问题的另一个解决方法
typedef void (*FunctionPointer)(int, int);
class Template
{
public:
template<typename Type>
static void Function(int Arg0, int Arg1)
{
// Code and Stuff
}
// ORIGINAL FUNCTION - Produces compile errors.
// Produces - error C2440: 'default argument' : cannot convert from 'overloaded-function' to 'FunctionPointer' (VS2012 SP5 x64)
template<typename Type>
void Original(FunctionPointer Arg = &Template::Function<Type>)
{
// Code and Stuff
}
// WORKAROUND FUNCTION - Compiles fine.
// Default Arg parameter to NULL and initialize default parameter inside function on runtime.
template<typename Type>
void Original(FunctionPointer Arg = NULL)
{
if (Arg == NULL)
Arg = &Template::Function<Type>;
// Code and Stuff
}
}
typedef void(*FunctionPointer)(int,int);
类模板
{
公众:
模板
静态无效函数(int Arg0,int Arg1)
{
//代码和东西
}
//原始函数-产生编译错误。
//生成-错误C2440:“默认参数”:无法从“重载函数”转换为“函数指针”(VS2012 SP5 x64)
模板
void Original(FunctionPointer Arg=&Template::Function)
{
//代码和东西
}
//变通功能-编译良好。
//默认参数为NULL,并在运行时初始化函数内部的默认参数。
模板
void Original(FunctionPointer Arg=NULL)
{
如果(Arg==NULL)
Arg=&模板::函数;
//代码和东西
}
}
您的编译器已损坏。使用&bar::foo
可能会有所帮助,因为它删除了对函数指针的隐式转换。将bar::foo
更改为&bar::foo
无效错误消息是否详细说明了转换无法进行的原因?是否可以删除typedef并直接指定类型?您是否在MS Connect上提交了错误报告?删除typedef并直接使用void(*)(
)没有帮助。我将向MS提交一份错误报告,因为这似乎不寻常。我不知道这是否相关,但您正在对bar::foo
进行显式专门化,这应该在相同的命名空间中完成,例如namespace bar{template void foo(){}
(由于bar::foo
语法,我最初认为bar
是一个类,因此我删除了答案)。