在 std::map 中使用 std::function
using std::function in a std::map
我有一个class...
#include <map>
#include <boost/function.hpp>
enum class ECmd { one, two, three };
class C
{
public:
void Command(ECmd e)
{
auto pos = m_fnCmd.find(e);
if (pos != m_fnCmd.end())
{
// call the function
(pos->second)(this);
}
else
{
printf("no command!\n");
}
}
protected:
using fnCmd = boost::function<void(C*)>;
using fnCmdMap = std::map<ECmd, fnCmd>;
static const fnCmdMap m_fnCmd;
// the command functions
void One() { printf("one.\n"); }
void Two() { printf("Two.\n"); }
void Three() { printf("Three.\n"); }
};
const C::fnCmdMap C::m_fnCmd =
{
{std::make_pair(ECmd::one, &C::One)},
{std::make_pair(ECmd::two, &C::Two)},
{std::make_pair(ECmd::three, &C::Three)},
};
这展示了我用于处理基于 id 的命令的技术。这段代码工作得很好,但是当我将 class 更改为使用 std::function 而不是 boost::function 时,它无法编译 - 不喜欢初始化 C::m_fnCmd.
错误信息是:
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(506): error C2664: 'void std::_Func_class<_Ret,C *>::_Set(std::_Func_base<_Ret,C *> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,C *> *'
1> with
1> [
1> _Ret=void
1> ]
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Do_alloc<_Myimpl,_Fret(__thiscall C::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> , _Fty=void (__thiscall C::* const &)(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Do_alloc<_Myimpl,_Fret(__thiscall C::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> , _Fty=void (__thiscall C::* const &)(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Reset_alloc<_Fret,C,,std::allocator<std::_Func_class<_Ret,C *>>>(_Fret (__thiscall C::* const )(void),_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Reset_alloc<_Fret,C,,std::allocator<std::_Func_class<_Ret,C *>>>(_Fret (__thiscall C::* const )(void),_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
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,C *>::_Reset<void,C,>(_Fret (__thiscall C::* const )(void))' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
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,C *>::_Reset<void,C,>(_Fret (__thiscall C::* const )(void))' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\utility(157) : see reference to function template instantiation 'std::function<void (C *)>::function<_From>(_Fx &&)' being compiled
1> with
1> [
1> _From=void (__thiscall C::* )(void)
1> , _Fx=void (__thiscall C::* )(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\utility(157) : see reference to function template instantiation 'std::function<void (C *)>::function<_From>(_Fx &&)' being compiled
1> with
1> [
1> _From=void (__thiscall C::* )(void)
1> , _Fx=void (__thiscall C::* )(void)
1> ]
1> c:\projects\test\fntest\fntest.cpp(60) : see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<ECmd,void(__thiscall C::* )(void),void>(std::pair<ECmd,void (__thiscall C::* )(void)> &&)' being compiled
1> with
1> [
1> _Kty=ECmd
1> , _Ty=C::fnCmd
1> ]
1> c:\projects\test\fntest\fntest.cpp(60) : see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<ECmd,void(__thiscall C::* )(void),void>(std::pair<ECmd,void (__thiscall C::* )(void)> &&)' being compiled
1> with
1> [
1> _Kty=ECmd
1> , _Ty=C::fnCmd
1> ]
1>
它适用于 GCC 和 Clang(请参阅 Jonathan 的评论)。为了使其在 VS2013 中工作,您可以在指向成员函数的指针周围添加 std::mem_fn():
const C::fnCmdMap C::m_fnCmd =
{
{std::make_pair(ECmd::one, std::mem_fn(&C::One))},
{std::make_pair(ECmd::two, std::mem_fn(&C::Two))},
{std::make_pair(ECmd::three, std::mem_fn(&C::Three))},
};
见VS2013 std::function with member function
我有一个class...
#include <map>
#include <boost/function.hpp>
enum class ECmd { one, two, three };
class C
{
public:
void Command(ECmd e)
{
auto pos = m_fnCmd.find(e);
if (pos != m_fnCmd.end())
{
// call the function
(pos->second)(this);
}
else
{
printf("no command!\n");
}
}
protected:
using fnCmd = boost::function<void(C*)>;
using fnCmdMap = std::map<ECmd, fnCmd>;
static const fnCmdMap m_fnCmd;
// the command functions
void One() { printf("one.\n"); }
void Two() { printf("Two.\n"); }
void Three() { printf("Three.\n"); }
};
const C::fnCmdMap C::m_fnCmd =
{
{std::make_pair(ECmd::one, &C::One)},
{std::make_pair(ECmd::two, &C::Two)},
{std::make_pair(ECmd::three, &C::Three)},
};
这展示了我用于处理基于 id 的命令的技术。这段代码工作得很好,但是当我将 class 更改为使用 std::function 而不是 boost::function 时,它无法编译 - 不喜欢初始化 C::m_fnCmd.
错误信息是:
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(506): error C2664: 'void std::_Func_class<_Ret,C *>::_Set(std::_Func_base<_Ret,C *> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,C *> *'
1> with
1> [
1> _Ret=void
1> ]
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Do_alloc<_Myimpl,_Fret(__thiscall C::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> , _Fty=void (__thiscall C::* const &)(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Do_alloc<_Myimpl,_Fret(__thiscall C::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> , _Fty=void (__thiscall C::* const &)(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Reset_alloc<_Fret,C,,std::allocator<std::_Func_class<_Ret,C *>>>(_Fret (__thiscall C::* const )(void),_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,C *>::_Reset_alloc<_Fret,C,,std::allocator<std::_Func_class<_Ret,C *>>>(_Fret (__thiscall C::* const )(void),_Alloc)' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> , _Alloc=std::allocator<std::_Func_class<void,C *>>
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,C *>::_Reset<void,C,>(_Fret (__thiscall C::* const )(void))' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
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,C *>::_Reset<void,C,>(_Fret (__thiscall C::* const )(void))' being compiled
1> with
1> [
1> _Ret=void
1> , _Fret=void
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\utility(157) : see reference to function template instantiation 'std::function<void (C *)>::function<_From>(_Fx &&)' being compiled
1> with
1> [
1> _From=void (__thiscall C::* )(void)
1> , _Fx=void (__thiscall C::* )(void)
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\utility(157) : see reference to function template instantiation 'std::function<void (C *)>::function<_From>(_Fx &&)' being compiled
1> with
1> [
1> _From=void (__thiscall C::* )(void)
1> , _Fx=void (__thiscall C::* )(void)
1> ]
1> c:\projects\test\fntest\fntest.cpp(60) : see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<ECmd,void(__thiscall C::* )(void),void>(std::pair<ECmd,void (__thiscall C::* )(void)> &&)' being compiled
1> with
1> [
1> _Kty=ECmd
1> , _Ty=C::fnCmd
1> ]
1> c:\projects\test\fntest\fntest.cpp(60) : see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<ECmd,void(__thiscall C::* )(void),void>(std::pair<ECmd,void (__thiscall C::* )(void)> &&)' being compiled
1> with
1> [
1> _Kty=ECmd
1> , _Ty=C::fnCmd
1> ]
1>
它适用于 GCC 和 Clang(请参阅 Jonathan 的评论)。为了使其在 VS2013 中工作,您可以在指向成员函数的指针周围添加 std::mem_fn():
const C::fnCmdMap C::m_fnCmd =
{
{std::make_pair(ECmd::one, std::mem_fn(&C::One))},
{std::make_pair(ECmd::two, std::mem_fn(&C::Two))},
{std::make_pair(ECmd::three, std::mem_fn(&C::Three))},
};
见VS2013 std::function with member function