読者です 読者をやめる 読者になる 読者になる

GLUTコールバック関数のテンプレート版

C++ OpenGL

GLUTのコールバック関数に関数オブジェクトが使えなかったので、
テンプレート版のコールバック関数を作ってみました。


リファレンス

namespace glut {

template <class F> void DisplayFunc(F f);         // f : void()
template <class F> void OverlayDisplayFunc(F f);  // f : void()
template <class F> void ReshapeFunc(F f);         // f : void(int width, int height)
template <class F> void MotionFunc(F f);          // f : void(int x, int y)
template <class F> void PassiveMotionFunc(F f);   // f : void(int x, int y)
template <class F> void KeyboardFunc(F f);        // f : void(unsigned char key, int x, int y)
template <class F> void KeyboardUpFunc(F f);      // f : void(unsigned char key, int x, int y)
template <class F> void MouseFunc(F f);           // f : void(int button, int state, int x, int y)
template <class F> void VisibilityFunc(F f);      // f : void(int state)
template <class F> void EntryFunc(F f);           // f : void(int state)
template <class F> void SpecialFunc(F f);         // f : void(int key, int x, int y)
template <class F> void SpecialUpFunc(F f);       // f : void(int key, int x, int y)
template <class F> void SpaceballMotionFunc(F f); // f : void(int x, int y, int z)
template <class F> void SpaceballRotateFunc(F f); // f : void(int x, int y, int z)
template <class F> void SpaceballButtonFunc(F f); // f : void(int button, int state)
template <class F> void ButtonBoxFunc(F f);       // f : void(int button, int state)
template <class F> void DialsFunc(F f);           // f : void(int dials, int value)
template <class F> void TabletMotionFunc(F f);    // f : void(int x, int y)
template <class F> void TabletButtonFunc(F f);    // f : void(int button, int state, int x, int y)
template <class F> void MenuStatusFunc(F f);      // f : void(int status, int x, int y)
template <class F> void MenuStateFunc(F f);       // f : void(int status)
template <class F> void WindowStatusFunc(F f);    // f : void(int state)
template <class F> void IdleFunc(F f);            // f : void()

// f : void(int value)
template <class F>
void TimerFunc(unsigned int msecs, F f, int value);

// f : void(unsigned int buttonMask, int x, int y, int z)
template <class F>
void JoystickFunc(F f, int pollInterval);

}


サンプル

#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "glut.hpp"

using namespace std;

struct disp {
    void operator()() const
    {
        cout << "描画" << endl;
    }
};

struct key_input {
    void operator()(unsigned char key, int x, int y) const
    {
        cout << "キーが押された" << endl;
    }
};

struct mouse_input {
    void operator()(int button, int state, int x, int y) const
    {
        cout << "マウスが押された" << endl;
    }
};

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitWindowPosition(300, 50);
    glutInitWindowSize(640, 480);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);

    glutCreateWindow("Title");

    // これ
    glut::KeyboardFunc(key_input());
    glut::MouseFunc(mouse_input());
    glut::DisplayFunc(disp());

    glutMainLoop();
}


以下ソース(glut.hpp)

#ifndef CPP_GLUT_INCLUDE
#define CPP_GLUT_INCLUDE

#include <GL/glut.h>
#include <boost/shared_ptr.hpp>

namespace glut {

//------------------------------------------------------//
// template <class F>                                   //
// void DisplayFunc(F f);                               //
//                                                      //
// glutDisplayFuncのテンプレート版                      //
//   fはvoid f()のシグニチャを持つ関数(オブジェクト)    //
//------------------------------------------------------//
namespace display_detail {

class functor_base {
public:
    virtual void invoke() = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke()
    {
        f_();
    }
};

static boost::shared_ptr<functor_base> display_functor_;

inline void dummyDisplayFunc()
{
    display_functor_->invoke();
}

} // namespace display_detail

template <class F>
inline void DisplayFunc(F f)
{
    using namespace display_detail;

    display_functor_.reset(new functor<F>(f));
    ::glutDisplayFunc(dummyDisplayFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void OverlayDisplayFunc(F f);                        //
//                                                      //
// glutOverlayDisplayFuncのテンプレート版               //
//   fはvoid f()のシグニチャを持つ関数(オブジェクト)    //
//------------------------------------------------------//
namespace display_detail {

static boost::shared_ptr<functor_base> overlay_display_functor_;

inline void dummyOverlayDisplayFunc()
{
    overlay_display_functor_->invoke();
}

} // namespace display_detail

template <class F>
inline void OverlayDisplayFunc(F f)
{
    using namespace display_detail;

    overlay_display_functor_.reset(new functor<F>(f));
    ::glutDisplayFunc(dummyOverlayDisplayFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void ReshapeFunc(F f);                               //
//                                                      //
// glutReshapeFuncのテンプレート版                      //
//   fはvoid f(int width, int height)の                 //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace reshape_detail {
    
class functor_base {
public:
    virtual void invoke(int width, int height) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}
    
    void invoke(int width, int height)
    {
        f_(width, height);
    }
};

static boost::shared_ptr<functor_base> reshape_functor_;

inline void dummyReshapeFunc(int width, int height)
{
    reshape_functor_->invoke(width, height);
}

} // namespace reshape_detail

template <class F>
inline void ReshapeFunc(F f)
{
    using namespace reshape_detail;
    
    reshape_functor_.reset(new functor<F>(f));
    ::glutReshapeFunc(dummyReshapeFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void MotionFunc(F f);                                //
//                                                      //
// glutMotionFuncのテンプレート版                       //
//   fはvoid f(int x, int y)の                          //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace motion_detail {

class functor_base {
public:
    virtual void invoke(int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}
    
    void invoke(int x, int y)
    {
        f_(x, y);
    }
};

static boost::shared_ptr<functor_base> motion_functor_;

inline void dummyMotionFunc(int x, int y)
{
    motion_functor_->invoke(x, y);
}

} // namespace motion_detail

template <class F>
inline void MotionFunc(F f)
{
    using namespace motion_detail;
    
    motion_functor_.reset(new functor<F>(f));
    ::glutMotionFunc(dummyMotionFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void PassiveMotionFunc(F f);                         //
//                                                      //
// glutPassiveMotionFuncのテンプレート版                //
//   fはvoid f(int x, int y)の                          //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace motion_detail {

static boost::shared_ptr<functor_base> passive_motion_functor_;

inline void dummyPassiveMotionFunc(int x, int y)
{
    passive_motion_functor_->invoke(x, y);
}

} // namespace motion_detail

template <class F>
inline void PassiveMotionFunc(F f)
{
    using namespace motion_detail;
    
    passive_motion_functor_.reset(new functor<F>(f));
    ::glutPassiveMotionFunc(dummyPassiveMotionFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void KeyboardFunc(F f);                              //
//                                                      //
// glutKeyboardFuncのテンプレート版                     //
//   fはvoid f(unsigned char key, int x, int y)の       //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace keyboard_detail {

class functor_base {
public:
    virtual void invoke(unsigned char key, int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(unsigned char key, int x, int y)
    {
        f_(key, x, y);
    }
};

static boost::shared_ptr<functor_base> keyboard_functor_;

inline void dummyKeyboardFunc(unsigned char key, int x, int y)
{
    keyboard_functor_->invoke(key, x, y);
}

} // namespace keyboard_detail

template <class F>
inline void KeyboardFunc(F f)
{
    using namespace keyboard_detail;

    keyboard_functor_.reset(new functor<F>(f));
    ::glutKeyboardFunc(dummyKeyboardFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void MouseFunc(F f);                                 //
//                                                      //
// glutMouseFuncのテンプレート版                        //
//   fはvoid f(int button, int state, int x, int y)の   //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace mouse_detail {

class functor_base {
public:
    virtual void invoke(int button, int state, int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int button, int state, int x, int y)
    {
        f_(button, state, x, y);
    }
};

static boost::shared_ptr<functor_base> mouse_functor_;

inline void dummyMouseFunc(int button, int state, int x, int y)
{
    mouse_functor_->invoke(button, state, x, y);
}

} // namespace mouse_detail

template <class F>
inline void MouseFunc(F f)
{
    using namespace mouse_detail;
    
    mouse_functor_.reset(new functor<F>(f));
    ::glutMouseFunc(dummyMouseFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void VisibilityFunc(F f);                            //
//                                                      //
// glutVisibilityFuncのテンプレート版                   //
//   fはvoid f(int state)の                             //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace state_detail {

class functor_base {
public:
    virtual void invoke(int state) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}
    
    void invoke(int state)
    {
        f_(state);
    }
};

static boost::shared_ptr<functor_base> visibility_functor_;

inline void dummyVisibilityFunc(int state)
{
    visibility_functor_->invoke(state);
}

} // namespace state_detail

template <class F>
inline void VisibilityFunc(F f)
{
    using namespace state_detail;
    
    visibility_functor_.reset(new functor<F>(f));
    ::glutVisibilityFunc(dummyVisibilityFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void EntryFunc(F f);                                 //
//                                                      //
// glutEntryFuncのテンプレート版                        //
//   fはvoid f(int state)の                             //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace state_detail {
    
static boost::shared_ptr<functor_base> entry_functor_;

inline void dummyEntryFunc(int state)
{
    entry_functor_->invoke(state);
}

} // namespace state_detail

template <class F>
inline void EntryFunc(F f)
{
    using namespace state_detail;
    
    entry_functor_.reset(new functor<F>(f));
    ::glutEntryFunc(dummyEntryFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void SpecialFunc(F f);                               //
//                                                      //
// glutSpecialFuncのテンプレート版                      //
//   fはvoid f(int key, int x, int y)の                 //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace special_detail {

class functor_base {
public:
    virtual void invoke(int key, int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int key, int x, int y)
    {
        f_(key, x, y);
    }
};

static boost::shared_ptr<functor_base> special_functor_;

inline void dummySpecialFunc(int key, int x, int y)
{
    special_functor_->invoke(key, x, y);
}

} // namespace special_detail

template <class F>
inline void SpecialFunc(F f)
{
    using namespace special_detail;

    special_functor_.reset(new functor<F>(f));
    ::glutSpecialFunc(dummySpecialFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void SpaceballMotionFunc(F f);                       //
//                                                      //
// glutSpaceballMotionFuncのテンプレート版              //
//   fはvoid f(int x, int y, int z)の                   //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace vector3_detail {

class functor_base {
public:
    virtual void invoke(int x, int y, int z) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int x, int y, int z)
    {
        f_(x, y, z);
    }
};

static boost::shared_ptr<functor_base> spaceball_motion_functor_;

inline void dummySpaceballMotionFunc(int x, int y, int z)
{
    spaceball_motion_functor_->invoke(x, y, z);
}
    
} // namespace vector3_detail

template <class F>
inline void SpaceballMotionFunc(F f)
{
    using namespace vector3_detail;

    spaceball_motion_functor_.reset(new functor<F>(f));
    ::glutSpaceballMotionFunc(dummySpaceballMotionFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void SpaceballRotateFunc(F f);                       //
//                                                      //
// glutSpaceballRotateFuncのテンプレート版              //
//   fはvoid f(int x, int y, int z)の                   //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace vector3_detail {

static boost::shared_ptr<functor_base> spaceball_rotate_functor_;

inline void dummySpaceballRotateFunc(int x, int y, int z)
{
    spaceball_rotate_functor_->invoke(x, y, z);
}
    
} // namesapce vector3_detail

template <class F>
inline void SpaceballRotateFunc(F f)
{
    using namespace vector3_detail;

    spaceball_rotate_functor_.reset(new functor<F>(f));
    ::glutSpaceballRotateFunc(dummySpaceballRotateFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void SpaceballButtonFunc(F f);                       //
//                                                      //
// glutSpaceballButtonFuncのテンプレート版              //
//   fはvoid f(int button, int state)の                 //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace button_state_detail {

class functor_base {
public:
    virtual void invoke(int button, int state) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int button, int state)
    {
        f_(button, state);
    }
};

static boost::shared_ptr<functor_base> spaceball_button_functor_;

inline void dummySpaceballButtonFunc(int button, int state)
{
    spaceball_button_functor_->invoke(button, state);
}
    
} // namespace button_state_detail

template <class F>
inline void SpaceballButtonFunc(F f)
{
    using namespace button_state_detail;

    spaceball_button_functor_.reset(new functor<F>(f));
    ::glutSpaceballButtonFunc(dummySpaceballButtonFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void ButtonBoxFunc(F f);                             //
//                                                      //
// glutButtonBoxFuncのテンプレート版                    //
//   fはvoid f(int button, int state)の                 //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace button_state_detail {

static boost::shared_ptr<functor_base> button_box_functor_;

inline void dummyButtonBoxFunc(int button, int state)
{
    button_box_functor_->invoke(button, state);
}
    
} // namespace button_state_detail

template <class F>
inline void ButtonBoxFunc(F f)
{
    using namespace button_state_detail;
    
    button_box_functor_.reset(new functor<F>(f));
    ::glutButtonBoxFunc(dummyButtonBoxFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void DialsFunc(F f);                                 //
//                                                      //
// glutDialsFuncのテンプレート版                        //
//   fはvoid f(int dials, int value)の                  //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace dials_detail {

class functor_base {
public:
    virtual void invoke(int dials, int value) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int dials, int value)
    {
        f_(dials, value);
    }
};

static boost::shared_ptr<functor_base> dials_functor_;

inline void dummyDialsFunc(int dials, int value)
{
    dials_functor_->invoke(dials, value);
}
    
} // namespace dials_detail

template <class F>
inline void DialsFunc(F f)
{
    using namespace dials_detail;

    dials_functor_.reset(new functor<F>(f));
    ::glutDialsFunc(dummyDialsFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void TabletMotionFunc(F f);                          //
//                                                      //
// glutTabletMotionFuncのテンプレート版                 //
//   fはvoid f(int x, int y)の                          //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace tablet_motion_detail {

class functor_base {
public:
    virtual void invoke(int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int x, int y)
    {
        f_(x, y);
    }
};

static boost::shared_ptr<functor_base> tablet_motion_functor_;

inline void dummyTabletMotionFunc(int x, int y)
{
    tablet_motion_functor_->invoke(x, y);
}
    
} // namespace tablet_motion_detail

template <class F>
inline void TabletMotionFunc(F f)
{
    using namespace tablet_motion_detail;

    tablet_motion_functor_.reset(new functor<F>(f));
    ::glutTabletMotionFunc(dummyTabletMotionFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void TabletButtonFunc(F f);                          //
//                                                      //
// glutTabletButtonFuncのテンプレート版                 //
//   fはvoid f(int button, int state, int x, int y)の   //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace tablet_button_detail {

class functor_base {
public:
    virtual void invoke(int button, int state, int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int button, int state, int x, int y)
    {
        f_(button, state, x, y);
    }
};

static boost::shared_ptr<functor_base> tablet_button_functor_;

inline void dummyTabletButtonFunc(int button, int state, int x, int y)
{
    tablet_button_functor_->invoke(button, state, x, y);
}
    
} // namespace tablet_button_detail

template <class F>
inline void TabletButtonFunc(F f)
{
    using namespace tablet_button_detail;

    tablet_button_functor_.reset(new functor<F>(f));
    ::glutTabletButtonFunc(dummyTabletButtonFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void MenuStatusFunc(F f);                            //
//                                                      //
// glutMenuStatusFuncのテンプレート版                   //
//   fはvoid f(int status, int x, int y)の              //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace menu_status_detail {

class functor_base {
public:
    virtual void invoke(int status, int x, int y) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int status, int x, int y)
    {
        f_(status, x, y);
    }
};

static boost::shared_ptr<functor_base> menu_status_functor_;

inline void dummyMenuStatusFunc(int status, int x, int y)
{
    menu_status_functor_->invoke(status, x, y);
}
    
} // namespace menu_status_detail

template <class F>
inline void MenuStatusFunc(F f)
{
    using namespace menu_status_detail;

    menu_status_functor_.reset(new functor<F>(f));
    ::glutMenuStatusFunc(dummyMenuStatusFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void MenuStateFunc(F f);                             //
//                                                      //
// glutMenuStateFuncのテンプレート版                    //
//   fはvoid f(int status)の                            //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace menu_state_detail {

class functor_base {
public:
    virtual void invoke(int status) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int status)
    {
        f_(status);
    }
};

static boost::shared_ptr<functor_base> menu_state_functor_;

inline void dummyMenuStateFunc(int status)
{
    menu_state_functor_->invoke(status);
}
    
} // namespace menu_state_detail

template <class F>
inline void MenuStateFunc(F f)
{
    using namespace menu_state_detail;

    menu_state_functor_.reset(new functor<F>(f));
    ::glutMenuStateFunc(dummyMenuStateFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void IdleFunc(F f);                                  //
//                                                      //
// glutIdleFuncのテンプレート版                         //
//   fはvoid f()の                                      //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace idle_detail {

class functor_base {
public:
    virtual void invoke() = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke()
    {
        f_();
    }
};

static boost::shared_ptr<functor_base> idle_functor_;

inline void dummyIdleFunc()
{
    idle_functor_->invoke();
}
    
} // namespace idle_detail

template <class F>
inline void IdleFunc(F f)
{
    using namespace idle_detail;

    idle_functor_.reset(new functor<F>(f));
    ::glutIdleFunc(dummyIdleFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void TimerFunc(unsigned int msecs, F f, int value);  //
//                                                      //
// glutTimerFuncのテンプレート版                        //
//   fはvoid f(int value)の                             //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace timer_detail {

class functor_base {
public:
    virtual void invoke(int value) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(int value)
    {
        f_(value);
    }
};

static boost::shared_ptr<functor_base> timer_functor_;

inline void dummyTimerFunc(int value)
{
    timer_functor_->invoke(value);
}
    
} // namespace timer_detail

template <class F>
inline void TimerFunc(unsigned int msecs, F f, int value)
{
    using namespace timer_detail;

    timer_functor_.reset(new functor<F>(f));
    ::glutTimerFunc(msecs, dummyTimerFunc, value);
}


//------------------------------------------------------//
// template <class F>                                   //
// void WindowStatusFunc(F f);                          //
//                                                      //
// glutWindowStatusFuncのテンプレート版                 //
//   fはvoid f(int state)の                             //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace state_detail {

static boost::shared_ptr<functor_base> window_status_functor_;

inline void dummyWindowStatusFunc(int state)
{
    window_status_functor_->invoke(state);
}

} // namespace state_detail

template <class F>
inline void WindowStatusFunc(F f)
{
    using namespace state_detail;

    window_status_functor_.reset(new functor<F>(f));
    ::glutWindowStatusFunc(dummyWindowStatusFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void KeyboardUpFunc(F f);                            //
//                                                      //
// glutKeyboardUpFuncのテンプレート版                   //
//   fはvoid f(unsigned char key, int x, int y)の       //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace keyboard_detail {

static boost::shared_ptr<functor_base> keyboard_up_functor_;

inline void dummyKeyboardUpFunc(unsigned char key, int x, int y)
{
    keyboard_up_functor_->invoke(key, x, y);
}

} // namespace keyboard_detail

template <class F>
inline void KeyboardUpFunc(F f)
{
    using namespace keyboard_detail;
    
    keyboard_up_functor_.reset(new functor<F>(f));
    ::glutKeyboardUpFunc(dummyKeyboardUpFunc);
}


//------------------------------------------------------//
// template <class F>                                   //
// void SpecialUpFunc(F f);                             //
//                                                      //
// glutSpecialUpFuncのテンプレート版                    //
//   fはvoid f(int key, int x, int y)の                 //
//   シグニチャを持つ関数(オブジェクト)                 //
//------------------------------------------------------//
namespace special_detail {

static boost::shared_ptr<functor_base> special_up_functor_;

inline void dummySpecialUpFunc(int key, int x, int y)
{
    special_up_functor_->invoke(key, x, y);
}

} // namespace special_detail

template <class F>
inline void SpecialUpFunc(F f)
{
    using namespace special_detail;
    
    special_up_functor_.reset(new functor<F>(f));
    ::glutSpecialUpFunc(dummySpecialUpFunc);
}


//--------------------------------------------------------------//
// template <class F>                                           //
// void JoystickFunc(F f, int pollInterval);                    //
//                                                              //
// glutJoystickFuncのテンプレート版                             //
//   fはvoid f(unsigned int buttonMask, int x, int y, int z)の  //
//   シグニチャを持つ関数(オブジェクト)                         //
//--------------------------------------------------------------//
namespace joystick_detail {

class functor_base {
public:
    virtual void invoke(unsigned int buttonMask, int x, int y, int z) = 0;
};

template <class F>
class functor : public functor_base {
    F f_;
public:
    functor(F f)
        : f_(f) {}

    void invoke(unsigned int buttonMask, int x, int y, int z)
    {
        f_(buttonMask, x, y, z);
    }
};

static boost::shared_ptr<functor_base> joystick_functor_;

inline void dummyJoystickFunc(unsigned int buttonMask, int x, int y, int z)
{
    joystick_functor_->invoke(buttonMask, x, y, z);
}

} // joystick_detail

template <class F>
inline void JoystickFunc(F f, int pollInterval)
{
    using namespace joystick_detail;

    joystick_functor_.reset(new functor<F>(f));
    ::glutJoystickFunc(dummyJoystickFunc, pollInterval);
}


} // namespace glut

#endif // CPP_GLUT_INCLUDE