使用 lambda 时出错

Error when using lambdas

本文关键字:出错 lambda 使用      更新时间:2023-10-16

我有一个类:

class InputMap
{
    public:
        template<typename Function>
        void setHotkey(sf::Keyboard::Key hotkey, Function onClick)
        {
            map[hotkey] = onClick;
        }
        void triggerHotkey(sf::Keyboard::Key hotkey)
        {
            if(map.find(hotkey) != map.end())
                map[hotkey]();
        }
    protected:
        std::map <sf::Keyboard::Key, std::function<void()>> map;
};

当像这样调用 setHotkey 函数时:

setHotkey(sf::Keyboard::Left, [=](){TestActor->move(sf::Vector2f(-20, 0));});
setHotkey(sf::Keyboard::Right, [=](){TestActor->move(sf::Vector2f(20, 0));});

我收到这些错误:

../Tyrant/include/Framework/InputMap.hpp|14|error: ‘void TGE::InputMap::setHotkey(sf::Keyboard::Key, Function) [with Function = TGE::State::setHotkey(sf::Keyboard::Key, Function) [with Function = TestState::enter()::__lambda2]::__lambda1]’, declared using local type ‘TGE::State::setHotkey(sf::Keyboard::Key, Function) [with Function = TestState::enter()::__lambda2]::__lambda1’, is used but never defined [-fpermissive]|
../Tyrant/include/Framework/InputMap.hpp|14|error: ‘void TGE::InputMap::setHotkey(sf::Keyboard::Key, Function) [with Function = TGE::State::setHotkey(sf::Keyboard::Key, Function) [with Function = TestState::enter()::__lambda3]::__lambda1]’, declared using local type ‘TGE::State::setHotkey(sf::Keyboard::Key, Function) [with Function = TestState::enter()::__lambda3]::__lambda1’, is used but never defined [-fpermissive]|
||=== Build finished: 2 errors, 1 warnings ===|

现在我猜我可以用 -permissive 编译,但我想避免这样做。

编辑:

显然,该错误是因为输入映射的.cpp文件包含

template<typename Function>
void setHotkey(sf::Keyboard::Key hotkey, Function onClick)
{
    map[hotkey] = onClick;
}

标题是

template<typename Function>
void setHotkey(sf::Keyboard::Key hotkey, Function onClick);

所以我想它不喜欢声明和实现在不同的文件中,可能是因为模板?有没有正确的方法可以做到这一点,还是我应该只在标题中使用它?

这是因为执行模板实例化的方式。

定义必须在实例化的翻译单元中完全可见。

将实现放在.cpp使定义仅在翻译单元中可见。

粗略地说,每个翻译单元.cpp一个文件(尽管我见过一些奇怪的、病态的、事情......

因此,若要解决问题,可以将实现移动到声明它的标头中。