C++ Keyboard Controller
Edit: Tested implementations below.

As jason says, returning either 0 or 1, looks like boolean. Change int to bool and return true or false.

Drop the std::string layer. It doesn't add anything over enum. And enum are just as readable and there is no way typos can appear with enums.

I don't have any experience with SDL myself, but I've written a keyboard -> action controller in an attempt at a game.

I'd also like to drop the std::map in favor of a std::vector. The trick is to use continuous enums and use those as indices for the std::vector.

Something like this:

enum class KeyboardEvents : byte
{
    ON_RELEASE,
    ON_PRESS,

    ORDINAL
};

typedef std::function&lt;void(void)&gt; keyboardFunc_t;

std::vector&lt;keyboardFunc_t&gt; keyboardEvents(KeyboardEvents::ORDINAL);

void bindControls()
{
    auto onReleaseLambda = [&amp;]()
    {
        // Do stuff
    };
    auto onPressLambda = [&amp;]()
    {
        // Do stuff
    };

    // Bind with lambdas
    keyboardEvents[KeyboardEvents::ON_RELEASE] = onReleaseLambda;
    keyboardEvents[KeyboardEvents::ON_PRESS] = onPressLambda;

    // Alternatively, use std::bind
    keyboardEvents[KeyboardEvents::ON_RELEASE] = std::bind(&amp;ClassName::onRelease, classInstancePtr);
    keyboardEvents[KeyboardEvents::ON_PRESS] = std::bind(&amp;ClassName::onPress, classInstancePtr);
}


I just wrote this on the top off my head. I'm not sure if it'll compile, but you get the idea.

I would also prefer lambdas in favor of std::bind.

As for storing std::shared_ptr&lt;ControllerContext&gt; controller_context_; in a raw or shared_ptr, I'd say neither. But DO use std::unique_ptr. Using a unique_ptr will make sure your controller class is not default copyable, which is a good thing when dealing with limited resources.

Like this std::unique_ptr&lt;ControllerContext&gt; controller_context_;

Edit: From here and on:

Note, don't look too closely on main.cpp, it was mainly copied from somewhere to get SDL2 running.

ControllerContext.h:

#ifndef SHMUPPY_HEADER_CONTROLLER_CONTEXT_H
#define SHMUPPY_HEADER_CONTROLLER_CONTEXT_H


#include &lt;vector&gt;
#include &lt;functional&gt;

struct ControllerContext
{

    ControllerContext()
        : keyPressEvents(SDL_NUM_SCANCODES)
        , keyReleaseEvents(SDL_NUM_SCANCODES)
    {
        keyPressEvents.resize(SDL_NUM_SCANCODES);
        keyReleaseEvents.resize(SDL_NUM_SCANCODES);
    }

    typedef std::function&lt;void(void)&gt;   KeyboardFunc_t;
    typedef std::vector&lt;KeyboardFunc_t&gt; KeyEvents;

    KeyEvents   keyPressEvents;
    KeyEvents   keyReleaseEvents;
};


typedef std::unique_ptr&lt;ControllerContext&gt;  ControllerContext_ptr;

#endif


keyboardcontroller.h:

#ifndef SHMUPPY_HEADER_KEYBOARDCONTROLLER_H_
#define SHMUPPY_HEADER_KEYBOARDCONTROLLER_H_

#include &lt;map&gt;
#include &lt;SDL.h&gt;
#include &lt;iostream&gt;
#include &lt;exception&gt;
#include &lt;string&gt;
#include &lt;memory&gt;


#include "ControllerContext.h"



class Controller
{
public:
    Controller();

    bool OnKeyPress(const SDL_Event &amp;e);

    bool OnKeyRelease(const SDL_Event &amp;e);

    // Clear by setting empty func
    void SetReleaseCallback(SDL_Scancode code, const ControllerContext::KeyboardFunc_t &amp; func);
    void SetPressCallback(SDL_Scancode code, const ControllerContext::KeyboardFunc_t &amp; func);

    // Clear both press and release
    void ClearCallback(SDL_Scancode code);

protected:
    ControllerContext_ptr controller_context_;
};


#endif


keyboardcontroller.cpp:

#include "KeyboardController.h"
#include "ControllerContext.h"


Controller::Controller()
    : controller_context_(new ControllerContext())
{
    //Some test initializations
    auto leftPress = [&amp;]()
    {
        // Left press lambda
        int debug=0;
    };
    auto leftRelease = [&amp;]()
    {
        // Left release lambda
        int debug=0;
    };

    SetPressCallback(SDL_SCANCODE_LEFT, leftPress);
    SetReleaseCallback(SDL_SCANCODE_LEFT, leftRelease);
}

bool Controller::OnKeyPress(const SDL_Event &amp;e)
{
    const auto &amp; scancode = e.key.keysym.scancode;

    const auto &amp; pressFunc = controller_context_-&gt;keyPressEvents[scancode];

    if (pressFunc)
    {
        // Call callback if valid
        pressFunc();
        return true;
    }

    return false;
}

bool Controller::OnKeyRelease(const SDL_Event &amp;e)
{
    const auto &amp; scancode = e.key.keysym.scancode;

    const auto &amp; pressFunc = controller_context_-&gt;keyReleaseEvents[scancode];

    if (pressFunc)
    {
        // Call callback if valid
        pressFunc();

        return true;
    }

    return false;
}

void Controller::SetReleaseCallback(SDL_Scancode code, const ControllerContext::KeyboardFunc_t &amp; func)
{
    controller_context_-&gt;keyReleaseEvents[code] = func; 
}

void Controller::SetPressCallback(SDL_Scancode code, const ControllerContext::KeyboardFunc_t &amp; func)
{
    controller_context_-&gt;keyPressEvents[code] = func;
}

void Controller::ClearCallback(SDL_Scancode code)
{
    controller_context_-&gt;keyPressEvents[code] = ControllerContext::KeyboardFunc_t();
    controller_context_-&gt;keyReleaseEvents[code] = ControllerContext::KeyboardFunc_t();
}


main.cpp:

#include &lt;SDL.h&gt;
#include &lt;iostream&gt;

class TestMain
{
    public:
        void handlePressW()
        {
            // W press
            int debug=0;
        }
        void handleReleaseW()
        {
            // W release
            int debug=0;
        }
};

#include "keyboardcontroller.h"

int _stdcall WinMain(struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance, char *lpszCmdLine, int nCmdShow)
{
    if (SDL_Init(SDL_INIT_EVERYTHING) &lt; 0)
    {
        /* Handle problem */
        fprintf(stderr, "%s\n", SDL_GetError());
    }
    SDL_Window* window = SDL_CreateWindow("Window caption", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 852, 480, 0);
    if (window == NULL)
    {
        /* Handle problem */
        fprintf(stderr, "%s\n", SDL_GetError());
        SDL_Quit();
    }
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    if (renderer == NULL)
    {
        /* Handle problem */
        fprintf(stderr, "%s\n", SDL_GetError());
        SDL_Quit();
    }


    Controller keycontroller;

    // Bind testmain methods
    TestMain testmain;
    keycontroller.SetPressCallback(SDL_SCANCODE_W, std::bind(&amp;TestMain::handlePressW, testmain));
    keycontroller.SetReleaseCallback(SDL_SCANCODE_W, std::bind(&amp;TestMain::handleReleaseW, testmain));


    bool running = true;
    while (running)
    {
        /* Clear the buffer of color, setting it to black */
        SDL_RenderClear(renderer);

        /* Draw the buffer into the window */
        SDL_RenderPresent(renderer);

        /* Handle input and events: */
        SDL_Event sdl_event;
        while (SDL_PollEvent(&amp;sdl_event) &gt; 0)
        {
            switch (sdl_event.type)
            {
                case(SDL_KEYDOWN):
                {
                    keycontroller.OnKeyPress(sdl_event);
                    break;
                }

                case(SDL_KEYUP):
                {
                    keycontroller.OnKeyRelease(sdl_event);
                    break;
                }


                case(SDL_QUIT):
                    running = false;
                    break;
            }

        }

        /* Run your logic. For example: */
    }

    SDL_Quit();

    return 0;
}