0

I have a class:

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;
};

and when calling the setHotkey function like so:

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

I get these errors:

../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 ===|

Now I'm guessing I could just compile with -fpermissive but I would like to avoid doing so.

EDIT:

Apparently the error was because the .cpp file for InputMap contained

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

and the header was

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

So I guess it doesn't like the declaration and implementation to be in different files, possibly because of the template? Is there a proper way to do this or am I supposed to have it in the header only?

igleyy
  • 605
  • 4
  • 16
Mike
  • 587
  • 1
  • 6
  • 11
  • You haven't provided enough code to reproduce the problem. Here is an example using your code which does not give an error: http://coliru.stacked-crooked.com/a/eca4700e759af6a2 – Vaughn Cato Nov 09 '13 at 01:03
  • I have tried adding as much as I possibly can, I can't reproduce the error outside of my actual project. http://ideone.com/LPrUdK Is it possible part of the error may be because inputmap, state, game, statemanager are all in a library and teststate is not? – Mike Nov 09 '13 at 01:46
  • Please see the edit. I found out what is wrong. – Mike Nov 09 '13 at 02:08

1 Answers1

0

It is because of the way template instantiation is performed.

The definition has to be fully visible within the translation unit in which it is instantiated.

Putting the implementation in a .cpp made the definition visible only within that translation unit.

Roughly speaking, one .cpp file per translation unit (though I have seen some strange, sick, things...).

So, to fix your problem, you can move the implementation into the header in which it is declared.

defube
  • 2,395
  • 1
  • 22
  • 34