Search code examples
c++classtemplatesmembershipvoid

How to pass void arguments in a class/function templates


Hey i'm trying to make a Button template class, which is constructed with the the button would recieve when pressed (such as mouse position), and a pointer to the function that should be called.

However buttons often return void and take no arguments (Buttons that you press and something happens: they don't take any arguments, they're pressed and then just do something.) so how would i generate the classes member functions since apparently i can't have void as an argument type?

Here's the source if it's helpful:

    template<typename Return = void, typename Arg1 = void, typename Arg2 = void> 
class Button 
{
private:
    boost::function<Return (Arg1, Arg2)> Function;
    //Return (*Function)(Arg1, Arg2);              // this didn't work so i tried boost::function

public:
    void Activate(Arg1, Arg2){ Function(Arg1, Arg2) ;};

    void SetFunction(Return (*Function)(Arg1, Arg2)){
        this->Function= Function;};

    //constructors
    Button(){ Function= 0;};

    Button( Return (*Function)(Arg1, Arg2)){  
        this->Function = &Function; };
};

Solution

  • You can specify a template specification of type void, for example, you could use the following variations of the templated class, button:

    template <typename rtnVal, typename Val1, typename Val2>
    class Button {
    private:
        rtnVal(*Function)( Val1 val1, Val2 val2 );
    
    public:
        Button() : Function( nullptr ) {}
    
        void SetFunction( rtnVal(*func)(Val1, Val2) ) {
            Function = func;
        }
    
        rtnVal RunFunction( Val1 val1, Val2 val2 ) { return Function( val1, val2 ); }
    };
    
    // Special void type, accepting arguments overload:
    template < typename Val1, typename Val2 >
    class Button< void, Val1, Val2 > {
    private:
        void(*Function)(Val1 val1, Val2 val2);
    
    public:
        Button() : Function( nullptr ) {}
    
        void SetFunction( void(*func)(Val1, Val2) ) {
            Function = func;
        }
    
        void RunFunction( Val1 val1, Val2 val2 ) { return Function( val1, val2 ); }
    
    };
    
    // Pure void type:
    template<>
    class Button<void, void, void> {
    private:
        void(*Function)( void );
    
    public:
        Button() : Function( nullptr ) {}
    
        void SetFunction( void(*func)() ) {
            Function = func;
        }
    
        void RunFunction() { 
            return Function();
        }
    };
    

    This then allows you to initialize and use void as arguments, for example, given a void function Print() the following would now be valid:

    void Print()
    {
        std::cout << "Function has been called" << std::endl;
    }
    
    int main()
    {
        Button< void, void, void > btn;
    
        btn.SetFunction( Print );
    
        btn.RunFunction();
    
        std::cout << "Finished";
    }
    

    I hope this helps to clear things up! :)

    Note: nullptr is a C++0x keyword, if your compiler hasn't implemented it use #define nullptr 0