tags:

views:

144

answers:

3

I just want to expand this following method into something more generic, which should accept any kind of argument and display it using MessageBox():

void alert(char *item)
{
  MessageBox(NULL, item,  "Message", MB_OK | MB_ICONINFORMATION);
}

Can anyone help?

+2  A: 

You could write something like the following:

template<typename T>
void alert(T item)
{
  MessageBox(NULL, boost::lexical_cast<std::string>(item).c_str(),  "Message", MB_OK | MB_ICONINFORMATION);
}

You should specialize boost::lexical_cast for any argument type you want since it supports limited range of types.


Another way is to use boost::format:

// helper class
class msg_helper_t {
public:
    msg_helper_t(const char* msg ) : fmt(msg) {}
    ~msg_helper_t() { 
        MessageBox(NULL, str( fmt ).c_str(),  "Message", MB_OK | MB_ICONINFORMATION); 
    }

    template <typename T>
    msg_helper_t& operator %(const T& value) {
        try {
            fmt % value;
        } catch ( std::exception e ) {
            // some exceptional actions
        }
        return *this;
    }
    template <>
    msg_helper_t& operator %(const CString& value) {
        try {
            fmt % value.GetString();
        } catch ( std::exception e ) {
            // some exceptional actions
        }
        return *this;
    }

protected:
    boost::format fmt;
};

// our message function
msg_helper_t MyMsgBox(const char* msg) { return msg_helper_t( msg ); }

Later it could be used in the following way:

   MyMsgBox( "Hello with %d arguments: %s" ) % 2 % "some text";
   MyMsgBox( "%d" ) % 123456;
   MyMsgBox( "%f" ) % 10.5f;
Kirill V. Lyadvinsky
+1 for beating me to it.
Glen
can we do it without using boost library ?
TuxGeek
MSalters
@UK: boost::lexical_cast<> is a simple template, you can nick the implementation without pulling all of Boost in.
MSalters
UK, you could make the same without boost (by using streams). But `boost` makes life easier.
Kirill V. Lyadvinsky
All lexical_cast does is basically create a std::stringstream, feed the variable to it, and extract the result using operator >>. So yes, you could easily do it without the boost library.
jalf
A: 

Since C++ is statically typed, you'll probably need to do one of two things:

  1. Use a class hierarchy and have alert take a pointer/reference to a base class which contains some kind of virtual "toString()" function (the Java/.NET approach). The downside here is that alert() now only works for types in that class hierarchy.
  2. Overload the alert function for types that can't be directly converted to a string, with the downside that you have to duplicate code.

Also, you should make sure to use MessageBoxA if you're using ANSI strings, otherwise you should consider using TCHAR and MessageBox or wchar_t and MessageBoxW.

Nick Meyer
+1  A: 
#include <sstream>
template<typename T>
void alert(T item)
{
//this accepts all types that supports operator << 
  std::ostringstream os;
  os << item;
  MessageBoxA(NULL, os.str().c_str(),  "Message", MB_OK | MB_ICONINFORMATION);
}

//now you need specialization for wide char
void alert(const wchar_t* item)
{

  MessageBoxW(NULL, item,  "Message", MB_OK | MB_ICONINFORMATION);
}
Dewfy
You're missing the declaration of `os` in the wide char case. Otherwise good answer. +1
jalf
@jalf - Thanks! just edited this.
Dewfy
first function works perfectly :)
TuxGeek
Second function isn't `specialization`. It is overloading. And you missed `;` in `os << item`.
Kirill V. Lyadvinsky