Alain's (original, now much hacked) narrow character version, could leak if std::basic_string<>::asign threw. To make the function exception safe either use a local buffer (if the size is fixed) or a vector (if the size isn't known).
In both cases it's usually more efficient (and readable) to return a string by value than construct it outside the function and essentially reconstruct it within the function. This doesn't help too much if you want the semantics of the windows LoadString but there's not a lot of reason to return the size of the loaded string. This information isn't needed in the wide character case and is useless in the narrow character case (it's always going to be less than the size passed into the function).
I'd be tempted to use:
[When I first wrote this I was seduced into the idea that you could directly initialise a string from a pointer and a length. However the C++ standard doesn't specify which order parameters are evaluated prior to a function call so we need to stick a sequence point in between the read and the string construction.]
std::wstring load_wstring_from_resource( HINSTANCE instance_handle, unsigned resource_id )
{
wchar_t *buffer = 0;
std::size_t string_length = LoadStringW(
instance_handle,
resource_id,
reinterpret_cast<wchar_t *>( &buffer ),
0 );
return std::wstring( buffer, string_length );
);
}
or:
std::string load_string_from_resource( HINSTANCE instance_handle, unsigned resource_id )
{
char buffer[ 1024 ] = { '\0' };
std::size_t string_length = LoadStringA(
instance_handle,
resource_id,
buffer,
1024 );
return std::string( buffer, string_length );
}
[Note that here you could get away with doing it all in one line as there's no way the location of buffer is going to change. However it leads more naturally onto the next one...]
And for those that really want big strings and dynamic memory allocation, you can get that by:
std::string load_string_from_resource( HINSTANCE instance_handle, unsigned resource_id, std::size_t max_size )
{
std::vector<char> buffer( max_size );
std::size_t string_length = LoadStringA(
instance_handle,
resource_id,
&buffer[ 0 ],
max_size );
return std::string( &buffer[ 0 ], string_length );
}
No exception handling required and is still exception safe. And on VC++ 2010 it's faster using the vector than manually handling exceptions from new[].
Just remember folks - new and delete, there's usually a better way. Be exception safe out there!
Ash
PS: Edited to buggery as I'd forgotten to escape a couple of angle brackets.
PPS: Edited more to buggery as I'd been making assumptions about the order of evaluation of parameters to functions.