std::bind 会导致非法的间接错误

std::bind causes illegal indirection error

本文关键字:错误 非法 bind std      更新时间:2023-10-16

我正在阅读SFML游戏开发书籍,但是我遇到了std::bind的问题。 我寻找解决方案,似乎其他人也有类似的问题。 但是,我仍然无法找到解决此特定问题的方法。 这是我的代码:

数据表.hpp

#ifndef DATA_TABLES_HPP
#define DATA_TABLES_HPP
#include <functional>
#include <vector>
struct PickupData {
    std::function<void(Aircraft&)> action;
}
std::vector<PickupData> initializePickupData();
#endif

数据表.cpp

using namespace std::placeholders;
std::vector<PickupData> initializePickupData() {
    std::vector<PickupData> data(static_cast<int>(Pickup::Type::TypeCount));
    data[static_cast<int>(Pickup::Type::HealthRefill)].action = std::bind(&Aircraft::repair, _1, 25);
    data[static_cast<int>(Pickup::Type::MissileRefill)].action = std::bind(&Aircraft::collectMissiles, _1, 3);
    data[static_cast<int>(Pickup::Type::FireSpread)].action = std::bind(&Aircraft::increaseSpread, _1);
    data[static_cast<int>(Pickup::Type::FireRate)].action = std::bind(&Aircraft::increaseFireRate, _1);
    return data;
}

实体.hpp

#ifndef ENTITY_HPP
#define ENTITY_HPP
class Entity {
    public:
        explicit Entity(int hitpoints);
        void repair(int points);
    protected:
        int hitpoints;
};
#endif

实体.cpp

#include "Entity.hpp"
#include <cassert>
Entity::Entity(int hitpoints)
    : hitpoints(hitpoints)
{}
void Entity::repair(int points) {
    assert(points > 0);
    hitpoints += points;
}

飞机.hpp

#ifndef AIRCRAFT_HPP
#define AIRCRAFT_HPP
class Aircraft : public Entity {
    public:
        Aircraft();
        void increaseFireRate();
        void increaseSpread();
        void collectMissiles(unsigned int count);
    private:
        int missileAmmo;
        int fireRateLevel;
        int spreadLevel;
}
#endif

飞机.cpp

#include "Aircraft.hpp"
Aircraft::Aircraft()
    : Entity(100)
    , missileAmmo(2)
    , fireRateLevel(1)
    , spreadLevel(1)
{}
void Aircraft::collectMissiles(unsigned int count) {
    missileAmmo += count;
}
void Aircraft::increaseSpread() {
    if (spreadLevel < 3)
        ++spreadLevel;
}
void Aircraft::increaseFireRate() {
    if (fireRateLevel < 10)
        ++fireRateLevel;
}

皮卡.hpp

#ifndef PICKUP_HPP
#define PICKUP_HPP
#include "Entity.hpp"
#include "Aircraft.hpp"
class Pickup : public Entity {
    public:
        enum class Type {
            HealthRefil,
            MissileRefill,
            FireSpread,
            FireRate,
            TypeCount
        }
        explicit Pickup(Type type);
        void apply(Aircraft& player) const;
    private:
        Type type;
}
#endif

皮卡.cpp

#include "Pickup.hpp"
#include "DataTables.hpp"
namespace {
    const std::vector<PickupData> Table = initializePickupData();
}
Pickup::Pickup(Type type)
    : Entity(1)
    , type(type)
{}
void Pickup::apply(Aircraft& player) const {
    Table[static_cast<int>(type)].action(player);
}

这是错误:

1>c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1241): error C2100: illegal indirection
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1149) : see reference to function template instantiation '_Rx std::_Pmf_wrap<void (__thiscall Entity::* )(int),_Rx,Entity,int>::operator ()<Aircraft>(_Wrapper &,int) const' being compiled
1>          with
1>          [
1>              _Rx=void
1>  ,            _Wrapper=Aircraft
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1149) : see reference to function template instantiation '_Rx std::_Pmf_wrap<void (__thiscall Entity::* )(int),_Rx,Entity,int>::operator ()<Aircraft>(_Wrapper &,int) const' being compiled
1>          with
1>          [
1>              _Rx=void
1>  ,            _Wrapper=Aircraft
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1137) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>::_Do_call<Aircraft,0,1>(std::tuple<Aircraft &>,std::_Arg_idx<0,1>)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1137) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>::_Do_call<Aircraft,0,1>(std::tuple<Aircraft &>,std::_Arg_idx<0,1>)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(283) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>::operator ()<Aircraft&>(Aircraft &)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(283) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>::operator ()<Aircraft&>(Aircraft &)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>,false>::_ApplyX<_Rx,Aircraft&>(Aircraft &)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>,false>::_ApplyX<_Rx,Aircraft&>(Aircraft &)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,Aircraft &>::_Do_call(Aircraft &)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>  ,            _Ret=void
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,Aircraft &>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>  ,            _Ret=void
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,Aircraft &>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,Aircraft &>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,Aircraft &>>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(688) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(688) : see reference to function template instantiation 'void std::_Func_class<_Ret,Aircraft &>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]
1>          c:usersalecdesktopc++ codesfmlprojectsfmlprojectdatatables.cpp(78) : see reference to function template instantiation 'std::function<void (Aircraft &)> &std::function<void (Aircraft &)>::operator =<std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]
1>          c:usersalecdesktopc++ codesfmlprojectsfmlprojectdatatables.cpp(78) : see reference to function template instantiation 'std::function<void (Aircraft &)> &std::function<void (Aircraft &)>::operator =<std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Entity::* )(int),void,Entity,int>,std::_Ph<1> &,int>
1>          ]

任何可能的解决方案将不胜感激。

所以问题出在这条线上:

data[static_cast<int>(Pickup::Type::HealthRefill)].action = 
  std::bind(&Aircraft::repair, _1, 25);

根据错误转储,actionstd::function<void(Aircraft&)>,但repair是基类 Entity 而不是 Aircraft 的成员。由于std::bind返回的时髦返回值,因此无法将其直接转换为std::function<void(Aircraft&)>。首先需要将返回值强制转换为std::function<void(Entity&)>,该值可以隐式转换为std::function<void(Aircraft&)>,然后再将其分配给操作。 即:

data[static_cast<int>(Pickup::Type::HealthRefill)].action = 
  (std::function<void(Entity &)>) std::bind(&Aircraft::repair, std::placeholders::_1, 25);