gpt4 book ai didi

c++ - 到 std::function 的可变参数模板转换适用于 GCC 而不是 MSVC2013,为什么?

转载 作者:IT老高 更新时间:2023-10-28 21:43:26 26 4
gpt4 key购买 nike

如果这是重复的,我很抱歉。但我在搜索中找不到任何内容。

我可以使用 c++11/c++14 的任何最新功能。如有必要,我可以升级到 VS2015。

我正在尝试编写一个类,该类在分配时将自动转换为具有特定签名的 std::function。我有适用于 GCC 的代码,但在 MSVC2013 上失败了。该代码是重新创建错误的片段。 WTF MSVC?!

我也知道这是有风险的代码,自动转换函数指针等,但它是用于插件库的私有(private)实现,我只想定义一次函数签名。

如果有另一种方法可以编写代码,在 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> ]

最佳答案

这是解决您的问题的另一种方法。如果我对 MSVC 2015 功能的理解是正确的,它应该在那里工作。

(我假设您的问题是希望相对透明地将 void* 转换为未知函数到具有未知函数实际具有的签名的 std::function,而不必重复函数的签名。)

而不是将 void 指针转换到我们被转换到 std::function 的位置。 ,而是在调用函数并通过“返回类型推导”技巧计算返回值(或者,当没有计算返回值时)时执行此操作:

template<class...Args>
struct void_ptr_deferred_execution_t {
std::tuple<Args&&...> args;
void const* pf = nullptr;
void_ptr_deferred_execution_t( std::tuple<Args&&...> a, void const* p ):
args(std::move(a)),
pf(p)
{}
template<class R, size_t...Is>
R invoke( std::index_sequence<Is...> ){
using f_t = R(*)(Args...);
f_t f = f_t(pf);
pf = nullptr;
return f(std::forward<Args>(std::get<Is>(args))...);
}
template<class R>
operator R()&&{
return invoke<R>( std::index_sequence_for<Args...>{} );
}
~void_ptr_deferred_execution_t() {
if (pf) invoke<void>(std::index_sequence_for<Args...>{});
}
};

class FunctionPointer
{
void* fp;
public:
FunctionPointer(void* ptr)
: fp(ptr)
{}

template<class...Args>
void_ptr_deferred_execution_t<Args...>
operator()(Args&&...args)const {
return { std::forward_as_tuple(std::forward<Args>(args)...), fp };
}
};

live example .

std::function调用它们的可调用对象,它们要么丢弃结果,要么将其转换为 R .从传递给可调用对象的参数,加上返回值转换为的类型,我可以(大部分)重构 std::function 的签名那叫我。

那时,我施放了我的 void*放入指向该函数的指针,调用它并返回结果。

如果我从未被强制转换为某事,在破坏点我将我的函数指针转换为 void返回函数,调用它,就完成了。


注意事项:

注意直接调用FunctionPointer就像将它传递给 std::function 一样危险在你的例子中(非常)。

真的,将函数指针存储在 std::function 中太过分了。

未在 MSVC2015 中测试,但我没有看到任何在 MSVC2015 中不起作用的东西。

std::function 的某些实现可能如果您的函数返回 void,则可能无法使用上述内容.然而,这将是一个编译时错误。

上面还假设没有带有右值引用参数的函数,因为在调用时,我无法区分是从 std::function<void(T)> 调用的。和 std::function<void(T&&)> .我猜是 void(T)在那种情况下。

关于c++ - 到 std::function<R(ARGS...)> 的可变参数模板转换适用于 GCC 而不是 MSVC2013,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31104938/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com