2008年12月2日 星期二

std::exception 沒有支援wchar_t的介面

很可惜的,如果你的程式是Unicode的話,exception::what並不會因此而改成傳回const wchar_t *

void log(const wchar_t* text);

void main()
{
try
{
throw std::runtime_error();
}
catch (std::exception& ex)
{
const char * message = ex.what(); // 只有const char *的版本
log(message);
}
}


一種做法是不要透過what去取得error message
(適用在寫自己的exception,底層的exception還是沒辦法)

class your_exception : public std::exception
{
public:
your_exception(std::wstring what) : m_what(what) {}
virtual ~your_exception() {}

virtual const wchar_t * message() const
{
return m_what.c_str();
}

private:
std::wstring m_what;
};

void log(const wchar_t* text);

void main()
{
try
{
throw your_exception("something error..");
}
catch (your_exception& ex)
{
const wchar_t * message = ex.message();
log(message);
}
}


但是這樣寫會有幾個問題
1. C++提供的std::exception沒辦法改寫出wchar_t的版本。
2. 如果底層真的會丟出std::exception,那你也要catch (std::exception& ex)才攔得下來,根本問題還是沒有解決。

另一種方法是後端再去把const char * 轉成wchar_t

std::wstring ToWString(const char* text)
{
std::wstring str;
size_t size = strlen(text) + 1;
str.resize(size );
MultiByteToWideChar(CP_ACP, 0, text, -1, &str[0], size);
return str;
}

void log(const wchar_t* text);

void main()
{
try
{
throw std::runtime_error();
}
catch (std::exception& ex)
{
const char * message = ex.what();
log(ToWString(message));
}


後記
1. 其實這個對有經驗的programmer根本不是問題,而且解法可能沒有太多種。
2. 所以這篇只是要做一個memo而已。 :)

沒有留言:

LinkWithin

Related Posts with Thumbnails