basic_string< TargetChar > convert( const basic_string< SourceChar > &sourceString, size_t ( *convertFunction )( TargetChar *dst, const SourceChar **src, size_t len, mbstate_t *state )) { constexpr auto LENGTH_ERROR = static_cast< size_t >( -1 ); mbstate_t state = mbstate_t(); // Find out how much space we need: const SourceChar *sourceStringData = sourceString.data(); size_t expectedTargetStringLength = convertFunction( nullptr, &sourceStringData, sourceString.length(), &state ); if ( expectedTargetStringLength == LENGTH_ERROR ) throw make_errno_system_error(); // Convert the string: basic_string< TargetChar > targetString( expectedTargetStringLength, TargetChar() ); size_t actualTargetStringLength = convertFunction( &targetString[ 0 ], &sourceStringData, sourceString.length(), &state ); if ( actualTargetStringLength == LENGTH_ERROR ) throw make_errno_system_error(); // Could all characters be converted? if ( expectedTargetStringLength != actualTargetStringLength ) throw system_error( make_error_code( errc::illegal_byte_sequence )); return targetString; }
TargetChar cast_char(SourceChar ch) { if (is_signed<TargetChar>::value != is_signed<SourceChar>::value) { if (is_signed<SourceChar>::value) { // source is signed, target is unsigned typedef typename make_unsigned<SourceChar>::type USourceChar; return TargetChar(USourceChar(ch)); } else { // source is unsigned, target is signed typedef typename make_signed<SourceChar>::type SSourceChar; return TargetChar(SSourceChar(ch)); } } else { // source and target has same signedness return TargetChar(ch); // just cast } }