Если для char и wchar_t существует переходящий тип TCHAR, то в STL такого типа нет, но ведь у нас и самих есть своя голова на плечах, что нам стоит его создать?
Пожалуй, именно такую задачу решать ну совсем не интересно, давайте решим более сложную, решим ее заодно с задачей "о переходящих типах".
Существует огромный набор функций и типов WinAPI, часть из которых так или иначе требует участия строкового типа данных. И существует аналогичный набор макросов, которы
81; отвечает за совместимость всех этих функций и типов.
Но зачем нам запоминать "кривые" названия макросов, типа _stprintf и _sntscanf_s, когда мы можем просто сформулировать некоторый набор правил, по которым формируются различия между этими типами и функциями в API:
#define W( name ) #define WCAT( l, r ) #define _W( name ) #define AW( name ) #define WCSTR( name ) #define _WCSTR( name )макрос WCAT( l, r ) нужен для подстановки литеры w между левой ( l ) и правой ( r ) частями имени типов и функций:
ANSI: _isspace_l, __argv, _vscprintf, ...
UNICODE: _iswspace_l, __wargv, _vscwprintf, ...
макрос W( name ) нужен для подстановки литеры w к имени типов и функций:
ANSI: main, std::string, ...
UNICODE: wmain, std::wstring, ...
макрос _W( name ) нужен для подстановки литер _w к имени типов и функций:
ANSI: fopen_s, remove, ...
UNICODE: _wfopen_s, _wremove, ...
макрос AW( name ) нужен для подстановки литеры A или W в конец имени типов и функций:
ANSI: CreateWindowA, SendMessageA, CREATESTRUCTA, ...
UNICODE: CreateWindowW, SendMessageW, CREATESTRUCTW, ...
макрос WCSTR( name ) нужен для подстановки префикса str или wcs к имени типов и функций:
ANSI: strlen, strncpy_s, strchr, ...
UNICODE: wcslen, wcsncpy_s, wcschr, ...
макрос _WCSTR( name ) нужен для подстановки префикса _str или _wcs к имени типов и функций:
ANSI: _strtod_l, _strtoi64, _strdup, ...
UNICODE: _wcstod_l, _wcstoi64, _wcsdup, ...
Реализация этих макросов может быть разной, вот только один из вариантов:
#ifndef UNICODE #define WCAT( l, r ) l ## r #define W( name ) name #define AW( name ) name ## A #define WCSTR( name ) str ## name #define _WCSTR( name ) _str ## name #else #define WCAT( l, r ) l ## w ## r #define W( name ) w ## name #define AW( name ) name ## W #define WCSTR( name ) wcs ## name #define _WCSTR( name ) _wcs ## name #endif #define _W( name ) WCAT( _, name )А теперь заменим все эти макросы одним, универсальным:
#ifndef UNICODE #define ucat( left, right, ansi, unicode ) left ## ansi ## right #else #define ucat( left, right, ansi, unicode ) left ## unicode ## right #endifи построим на его основе, для наглядности, все остальные:
#define WCAT( l, r ) ucat( l, r, , w ) #define W( name ) ucat( , name, , w ) #define AW( name ) ucat( name, , A, W ) #define WCSTR( name ) ucat( , name, str, wcs ) #define _WCSTR( name ) ucat( _, name, str, wcs ) #define _W( name ) ucat( _, name, , w )да, можно заметить, макросы адекватно востпринимают отсутствие каких-либо идентификаторов между запятыми, такое поведение препроцессора и позволяет использовать всего лишь один макрос, лично я дополнительно пользуюсь только такими:
#define w( left, right ) ucat( left, right, , w ) #define W( left, right ) ucat( left, right, , W )примеры:
w( , main )( ... ); // main/wmain w( __, argv )[...]; // __argv/__wargv W( _CrtDbgReport, )( ... ); // _CrtDbgReport/_CrtDbgReportW ucat( SendMessage, , A, W )( ... ); // SendMessageA/SendMessageW ucat( ,len , str, wcs )( ... ); // strlen/wcslen ucat( _, icmp, str, wcs )( ... ); // _stricmp/_wcsicmp
в следующей статье производится унификация таких правил
Комментариев нет:
Отправить комментарий