привет!
в рамках очередного проекта надо перевести программу с анси на юникод. перво-наперво хочется уйти от выходов за границы буферов, которые сплошь и рядом возможны в местах подобных такому:
TCHAR valName[MAX_PATH];
for( DWORD i = 0, valNameSize = sizeof(valName);
ERROR_SUCCESS == RegEnumValue(key.m_hKey, i, valName, &valNameSize, NULL, NULL, NULL, NULL);
++i, valNameSize = sizeof_arr(valName))
пока массив valName был char[], размер буффера соответствовал размеру sizeof(valName), когда он стал wchar_t[], передаваемый RegEnumValue размер стал больше, чем сам буффер, и стало возможно переполнение.
определять размер статического массива очень удобно с помощью макроса, найденного мной на этом форуме:
template<class T, std::size_t N>
char(&sizeof_funca(T(&)[N]))[N];
#define lengthof_arr(arr) sizeof(unicodization::sizeof_funca(arr))
великолепие этого подхода состоит в том, что данному макросу можно передать только переменную-массив, ничто другое не скомпилится. была идея подменить sizeof lengthof_arr и исправить все ошибки, которые возникают в результате компиляции. т.е. код, приведенный в первом примере, скомпилился бы, а вот код типа
int i = sizeof(int);
int j = sizeof(i);
компиляться бы отказался, и нужно было бы sizeof на что-то менять. мне показалось, что будет логично заменить на что-то похожее на
int i = lengthof_type(int);
int j = lengthof_val(i);
и очень хочется, чтобы lengthof_type можно было использовать только с типом, и lengthof_val только со значением. указатели хочется исключить.
вот что у меня получилось:
namespace unicodization
{
template<class T, std::size_t N>
char(&sizeof_funca(T(&)[N]))[N];
template<class T, std::size_t N>
struct sizeof_class;
template<class T>
struct sizeof_class<T, 0>{ char size[sizeof(T)]; };
template<class T>
struct sizeof_class<T*, 0>;
template<typename T>
sizeof_class<T, 0>(&sizeof_funcv(T&));
template<class T, std::size_t N>
sizeof_class<T, N>(&sizeof_funcv(T(&)[N]));
template<typename T>
struct type_check{ typedef T thetype;char size[sizeof(T)]; };
}
#define lengthof_arr(arr) sizeof(unicodization::sizeof_funca(arr))
#define lengthof_val(val) sizeof(unicodization::sizeof_funcv(val))
#define lengthof_type(t) sizeof(unicodization::type_check< t >)
#define sizeof(x) sizeof_arr(x)
по ходу исправления ошибок я проверяю, какой именно сайзоф нужен,и ставлю именно его. заключительном этапом является исправление всех sizeof на lengthof_arr и раздефайниванием сайзофа.
какие камни я не увидел, может есть что-то проще?