【发布时间】:2015-09-15 06:46:32
【问题描述】:
如果这是重复的,我很抱歉。但我在搜索中找不到任何内容。
我可以使用 c++11/c++14 的任何最新功能。如有必要,我可以升级到 VS2015。
我正在尝试编写一个类,该类在分配时将自动转换为具有特定签名的 std::function。我有适用于 GCC 的代码,但在 MSVC2013 上失败了。该代码是一个重新创建错误的 sn-p。 WTF MSVC?!
我也知道这是有风险的代码,自动转换函数指针等,但它是用于插件库的私有实现,我只想定义一次函数签名。
如果有另一种方法来编写代码,在 main() 中完成相同的功能并同时在两者上工作,我会全力以赴。
GCC c++11 工作正常 - Demo
#include <functional>
#include <string>
#include <iostream>
class FunctionPointer
{
void* fp;
public:
FunctionPointer(void* ptr)
: fp(ptr)
{}
// Overload casting operator to
// a certain function signiture
template<class R, class... ARGS>
operator std::function<R(ARGS...)>(){
typedef R(*func_ptr)(ARGS...);
return std::function<R(ARGS...)>((func_ptr)fp);
}
};
void hello(std::string msg){
std::cout << "Hello " << msg << std::endl;
}
int main() {
FunctionPointer f((void*)hello);
std::function<void(std::string)> func_hello = f;
func_hello("World!");
return 0;
}
当我将行更改为此时,MSVC 工作......
std::function<void(std::string)> func_hello = f.operator std::function<void(std::string)>();
当我遇到这个时,MSVC 失败并出现同样的错误...
std::function<void(std::string)> func_hello = (std::function<void(std::string)>)f;
MSVC 在一个文件中出现以下错误,至少可以说是难以阅读。似乎是在推断错误的函数签名。
xrefwrap.h:283 - error C2064: term does not evaluate to a function taking 1 arguments
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283): error C2064: term does not evaluate to a function taking 1 arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<FunctionPointer,false>::_ApplyX<_Rx,_Ty>(_Ty &&)' being compiled
1> with
1> [
1> _Ret=void
1> , _Rx=void
1> , _Ty=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<FunctionPointer,false>::_ApplyX<_Rx,_Ty>(_Ty &&)' being compiled
1> with
1> [
1> _Ret=void
1> , _Rx=void
1> , _Ty=std::basic_string<char,std::char_traits<char>,std::allocator<char>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,std::string>::_Do_call(std::string &&)'
1> with
1> [
1> _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> , _Ret=void
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,std::string>' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> , _Ret=void
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Do_alloc<_Myimpl,FunctionPointer&,_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> , _Fty=FunctionPointer &
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Do_alloc<_Myimpl,FunctionPointer&,_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> , _Fty=FunctionPointer &
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Reset_alloc<FunctionPointer&,std::allocator<std::_Func_class<_Ret,std::string>>>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fty=FunctionPointer &
1> , _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Reset_alloc<FunctionPointer&,std::allocator<std::_Func_class<_Ret,std::string>>>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fty=FunctionPointer &
1> , _Alloc=std::allocator<std::_Func_class<void,std::string>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Reset<FunctionPointer&>(_Fty)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fty=FunctionPointer &
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::string>::_Reset<FunctionPointer&>(_Fty)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fty=FunctionPointer &
1> ]
1> c:\users\cameron\desktop\desktop\programming\projects\c++ projects\garbage\templatetest\main.cpp(32) : see reference to function template instantiation 'std::function<void (std::string)>::function<FunctionPointer&>(_Fx)' being compiled
1> with
1> [
1> _Fx=FunctionPointer &
1> ]
1> c:\users\cameron\desktop\desktop\programming\projects\c++ projects\garbage\templatetest\main.cpp(32) : see reference to function template instantiation 'std::function<void (std::string)>::function<FunctionPointer&>(_Fx)' being compiled
1> with
1> [
1> _Fx=FunctionPointer &
1> ]
【问题讨论】:
-
其中至少有一部分是“
std::function有一个构造函数,它可以接受阳光下的一切”问题。这是标准中已修复的缺陷,但修复需要表达式 SFINAE 来实现,而 MSVC 尚不支持。 -
简单。只需去掉
FunctionPointer,直接从hello构造func_hello。在您的示例 main 中没有理由通过void*往返。您的实际代码库中可能有原因,但我没有看到任何证据,我对此表示怀疑。 -
@Yakk:但是 GetProcAddress()/dlsym() 兄弟。
-
这将违背所有明智的建议,但是由于您说这仅供内部使用,并且您应该确切地知道自己在做什么,所以这里是:
my::function模板派生自std::function,构造函数采用void*,它与您的转换函数基本相同。这意味着您摆脱了FunctionPointer并直接使用void*。您仅将其用于初始化;当你传递它时,你复制/绑定到std::function的引用。 -
抱歉,我只是想围绕您要完成的事情来思考一下,以便我可以提出其他建议。 FunctionPointer 直接使用 std::function 给你带来了什么?类型擦除?
标签: c++ c++11 variadic-templates c++14