Hi, everyone.

I am stuck in such a situation:
When failing to open a file, of which the name is in Unicode, I need to show the user something like "Can't open file: \My Document\file-name-in-unicode.txt" by throwing an exception . I often use exceptions this way(is this a good way?).

I am on Windows Mobile, and everything string is in Unicode. I would like to use all the C++ features in my program and when I tried the standard exception classes, I was stuck. the standard exception classes does not support Unicode. I know this is because the C++ language was designed before Unicode was ever a major thing. The exception classes are not designed using template, the what() function only returns a char*.

So, I am just seeking a workaroud, how would you do when using std::exception (either deriving from it or just using its subclasses) with Unicode?

Recommended Answers

All 11 Replies

You can do something like this :

#include <iostream>
#include <string>
#include <stdexcept>

using namespace std;

class Trouble : public std::exception
{
private:
	string errMsg;
public:
	Trouble(const wstring msg)
		 //convert from wstring to string
		: exception( string(msg.begin(), msg.end() ).c_str() )
	{
		errMsg = string( msg.begin(), msg.end() );	
               //testing
              throw *this;	
	}
};

int main()
{ 	
	try{
		Trouble(L"testing");
	}
	catch(Trouble& e){
		cout << e.what() << endl;
	}
	return 0;
}

Although its probably not portable.

Hi, firstPerson, Thank you for your reply.
The solution you offer does not work here.
The Unicode message I am going to output in my program is real multi-byte(two bytes per character), and string(wstring.begin(), wstring.end()) won't do the conversion correctly.

By the way, I find no way to edit my original post, the title was "How to use the C++ standard exception classes with Unicode?"

In general, if you're displaying error messages to the user based on what() of an exception that was thrown, you are probably doing something wrong.

The code that throws an exception is very unlikely to be able to compose a relevant and user-comprehensible error message at the point an exception is thrown. Exceptions are for communicating errors between sections of code and are not designed to be for user-consumption. They are not designed to be localizable (why would they be? An exception could be thrown by code very far away from the user). The code that catches the exception should inspect it to find out what it is about, and display the error message accordingly.

You can always define your own class derived from std::exception which stores std::wstring inside it, and use that for all your exceptions. But it would perhaps be the wrong error handling idiom to use.

The Boost error handling guidelines covers this aspect well:

Don't worry too much about the what() message. It's nice to have a message that a programmer stands a chance of figuring out, but you're very unlikely to be able to compose a relevant and user-comprehensible error message at the point an exception is thrown. Certainly, internationalization is beyond the scope of the exception class author. Peter Dimov makes an excellent argument that the proper use of a what() string is to serve as a key into a table of error message formatters.

from http://www.boost.org/community/error_handling.html

Hi, vijayan121
I had read the error Boost handling guidline before I started this thread here. I don't think that the article says is 100% correct(I might be wrong though).

So when and where can I compose a relevant and user-comprehensible error message if it is not at the point an exception is thrown? Let's hypothesize a such situation: My program tries to open a file, as we know there're many chances the action will fail, the file might not exist, or it might be in use...
I will do something like this:

...arg = "acb.txt";
int ret = openfile(arg);
if (ret == 1) throw except(string("file not found: ").append(arg));
else if (ret == 2) throw except("file in use.");
else if...

and catch the exception in a higher level, may be the outermost level:

try {
	....
} catch (const except& ex) {
	showMsg(ex.what());
}

Here I know what exactly happened, and I want to show this message to the user, is the "file not found" message not relevant enough or not comprehensible for the user to figure out what went wrong? I compose this message right at the point the exception is thrown.
Well, I am not going to do internationalization, so I don't want to do something like this "throw except("FILE_NOT_FOUND");" where the "FILE_NOT_FOUND" is a key mapping to an erorr message table.

But still, all this we have been talking about, does not address my original problem. the Win32 API MessageBox() which I use to show an INFO/ERROR message to the user, requires unicode arguments. I can not use the what() function of the std::exception for any purpose here.
If I derive from std::exception and add a wide version what(), which returns wchar_t*, and just use this wide version what() function, I see no relevancy deriving from std::exception.

Please correct me if I am understanding all this wrongly.

In this specific case (file not found), the what() of the exception may make sense to the user. But more often, for instance, if a std::vector<> throws a std::out_of_range, it is meaningful only to to the code (programmer) and not to the end-user.

It is never a good idea to create your own exception classes which are not related to the <stdexcept> heirarchy. Standard exceptions like std::bad_aloc, std::bad_cast and std::bad_exception are thrown by the implementation and the standard library components throw exceptions like std::out_of_range. It makes error handling easier if you do not have to have two separate catch expressions every time; a single catch( const std::runtime_error& ) should be able to catch all run time errors.

There are two ways to address your specific problem.

The first, and much simpler one (which I prefer) is to right a function to convert the what() of an exception to a wide character string.

std::wstring what2wstr( const std::exception& ex )
{
    // convert ex.what() to a wide character string and return it
    // trivially done here, ok for US-ASCII in UTF-8 => UNICODE
    std::string str( ex.what() ) ;
    std::wstring wstr( str.size(), ' ' ) ;
    std::copy( str.begin(), str.end(), wstr.begin() ) ;
    return wstr ;
}

The second is to create an exception base class with a wwhat() that returns a wide character string, and then multiply inherit your exceptions from this and one of the standard exception classes.

struct wchar_exception
{
    virtual const wchar_t* wwhat() const { return wmsg ; }

    protected: explicit wchar_exception( const char* msg ) throw() ;

    private:
       enum { MAX_MSG_SIZE = 255 } ;
       wchar_t wmsg[ MAX_MSG_SIZE + 1 ] ;
};

wchar_exception::wchar_exception( const char* msg ) throw()
{
    // convert msg to a wide character string and place it into wmsg
    // trivially done here, ok for US-ASCII in UTF-8 => UNICODE
    wchar_t* ptr = wmsg ;
    while( ( *ptr++ = *msg++ ) ) ;
}

struct file_not_found : public virtual std::runtime_error,
                        public virtual wchar_exception
{
    explicit file_not_found( const char* msg ) throw()
           : std::runtime_error(msg), wchar_exception(msg) {}
};

This is the kind of code that you would write at the point of catching the exception:

int main()
{
    try
    {
        throw file_not_found( "file 'this_file_is_just_not.there' not found" ) ;
    }

    catch( const std::exception& ex )
    {
        std::cout << "what: " << ex.what() << '\n' ;
        std::wcout << "what2wstr: " << what2wstr(ex) << '\n' ;
        try
        {
            const wchar_exception& wce = dynamic_cast< const wchar_exception& >(ex) ;
            std::wcout << "wwhat: " << wce.wwhat() << L'\n' ;
        }
        catch( const std::bad_cast& )
        {
            // this is a standard exception like std::bad_alloc
            // const char* msg = rte.what() ;
            // translate msg to wide characters, display it
        }
    }
}

Hi, vijayan121
With the two methods you mentioned, I have to do conversions, which I was trying to get rid of.
BTW, std::copy( str.begin(), str.end(), wstr.begin() ) does not work for multi-byte characters, I test it with Chinese.
Thank you all the same for spending your time for trying to offer solutions.

IMHO, I still think that handling the exceptions this way is much more elegant.

class MyException {
private:
	int _errCode;
public:
	MyException (const wchar_t* msg, int errCode = 0);
	const wchar_t* myWhat() const;
};

try {
	//...some code would cause either MyException or std exceptions
} catch (const MyException& e) {
	//here I can easily compose a relevant error message with the error code provided when constructing the exception, and show it to the end user.
	::MessageBox(e.myWhat() ....);
} catch (const std::exception& e) {	//catch all other std exceptions
	//...do something with the exception
	//I will have to do the conversion for the char* string returned by what() if I need it at all
}

With two catches, I no longer need to do the conversion either from wchar_t* to char* or from char* to wchar_t*.
I can easily construct MyException with a wide character string(you know, everything string on Windows Mobile is in Unicode.), this would be really convenient.
I don't think it would do me any harm by handling exceptions this way, Well I don't know why deriving from std::exception is always recommended.


Any opinion is welcome.

Here I know what exactly happened, and I want to show this message to the user

This is your major problem - exceptions should not be used for handling user errors, and users shouldn't need to know about exceptions which have occurred in your program - That is to say, if the user does need to know about it, then its not really an exception.

If you know exactly what happened, then you can deal with it in some other way. Exceptions are generally used for handling mistakes which you or another programmer might make when using your code - where those mistakes affect the inner workings of something else; for example, passing invalid data to a constructor or running an iterator or loop beyond the boundaries of a container. - situations where the best solution to a problem is to throw the error back to the calling code, and let that code clean up any mess which may have been left over.

You may be approaching C++ exceptions with a Java mindset, where exceptions are often used to handle all kinds of things (obviously, C++ is not Java). In C++ you should only use exceptions to handle circumstances which are truly exceptional - user interaction really isn't one of those things, since you should always be expecting that a user is likely type in something wrong, and don't really need to throw errors back to calling code.

Most of the time validation which can decay into a true/false check will suffice - and the problem can be effectively dealt with in the same place as code which retrieved input from the user in the first place.

exceptions should not be used for handling user errors, and users shouldn't need to know about exceptions which have occurred in your program - That is to say, if the user does need to know about it, then its not really an exception.

It seems you are going back to the C world where there are no exceptions, you just check return values of functions, and determine what happens by comparing the return value with a bunch of ERROR CODEs(because a value of true or false might not always suffice to indicate situations where the program would fail, say, opening a file, there are many reasons that the action would fail), and I believe you would prompt the user what to do next. This is fine, but it's kinda messy, you are just always delaying the handling code to be inside the calling function, I don't think such kind of code is elegant and more easy to maintain than that handled using exceptions.

With exceptions, you have the flexibility that the exception mechanism has to offer(some overhead though), you can handle all such kind of errors (user typing in error...) easily, you can handle the exception at any level as you see fit.

I come from a Java programmer. I confess sometimes I think of a C++ question with a Java mindset. But I wonder why C++ exceptions and Java Exceptions should be treated differently, they are all Object Oriented languages, and we all know that Java derives most of its features from C++, including the exception handling mechanism, what makes you think C++ exceptions should be used in a way so differently than Java?

Yes, both Java and C++ support handling of errors by using exceptions, both have keywords throw, try and catch which behave similarly. But this similarity is deceptive, the philosophy behind the exception mechanism is fundamentally different in the two languages.

The Java mechanism requires you to deal with potential errors at the specific places that they might occur. You accomplish this with try...finally blocks; if you open a file, you wrap that and the code that follows in a try...finally construct and close the file in the finally block. Not too bad, but you have to recognize when you need to do it and consciously put it in place. Not fundamentally different from the C technique of checking a return value or a global errno and clean up in the face of errors at or near the point where the error occurred.

It is telling that C++ has no finally. It has something far slicker — RAII (Resource Acquisition Is Initialization). Essentially you use objects that encapsulate resources which have destructors that do the clean up for you if things go wrong. One example of this is the iostream library. fstreambuff destructors release the memory for the file buffer, and fstream destructors close the file. Say, you create a file stream, and open a file for output, and an exception is thrown, the file is automatically closed during the stack unwind. Without the programmer having to do anything special or write any extra code.

void some_function( object x )
{
    x.a_method() ;

    std::ofstream file( path ) ;

    x.save(file) ;

    x.another_method() ; // may throw an exception!

    // etc
}

What this implies is that the code is not littered with try ... catch or try ... finally constructs; you write error handling code only at the place where you know how to handle that particular error. This means that an exception may be caught and examined in a place very far away from where it was thrown. try ... catch constructs are far fewer, and there is no tight coupling in between the code that reports an error and the code that eventually handles the error.

Programming this way (with exception safety) in C++ requires foresight and thinking of a different kind than Java. Classes must be designed to have good, predictable behavior in the presence of exceptions. Once this is done, the programmer’s job becomes far easier; rather than think about what cleanup needs to happen at every place in code, one just writes all their code as if errors that you know nothing about do not exist.

For an overview of programming in C++ with exception safety in mind, see:
http://www.informit.com/articles/printerfriendly.aspx?p=21084

For a more detailed discussion on exception safety and techniques for writing exception-safe code in C++, see:
http://www.research.att.com/~bs/3rd_safe.pdf

Hi, vijayan121, Thanks for the detailed explanation. It was really helpful. But I still need some time to digest it. ^_^
Thank you!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.