2016-03-15 2 views
3

Я хотел бы static_assert(), что подпись широких символов (L'x') соответствует значению wchar_t.static_assert подпись широких букв символов?

Определение wchar_t является моим собственным. (Я внедряю стандартную библиотеку C.) Я хотел бы провалиться раньше, не получится громко, если у компилятора, используемого пользователем, есть другое представление о широком значении символов, чем то, что настроено в библиотеке.

Утверждая комбинационной размер типов легко:

static_assert(sizeof(wchar_t) == sizeof(L'x'), "size matches"); 

Для встроено типа char, тестирование знаковость легко. Предполагая, что существует _CHAR_IS_SIGNED определяется либо 0, либо 1 где-то,

static_assert(((char)-1 < 0) == _CHAR_IS_SIGNED, "char is signed"); 

делает трюк.

Но wchar_t является не является встроенным типом ...

Есть ли способ сделать это (статическое) утверждение в «чистом» С99 или С11, то есть, не полагаясь на расширениях конкретного компилятора?


Разъяснение:

Я "" библиотека. У меня есть typedef некоторый целочисленный тип до wchar_t.

Компилятор - не я - определяет широкие литералы символов для некоторого типа. Этот тип не присвоил имя компилятору, но в идеале должен быть идентичен тому, что я использую для wchar_t, включая подпись (которая, AFAICT, не указана стандартом).

Я хотел бы утвердить/проверить идентичность этих типов в некотором роде. Ошибка (type)-1 < 0, указанная для char выше, не работает, , потому что я не могу назвать «тип, используемый компилятором для литералов».

+0

Сверху моей головы: литье '-1' в требуемый тип? – LPs

+1

@LPs: Вопрос в основном, как мне придать '-1'' typeof (L'x ') 'без такой вещи, как' typeof() '? – DevSolar

+0

'_CHAR_IS_SIGNED' не является стандартным макросом. Лучшим подходом было бы обеспечить соблюдение 'signed' или' unsigned' 'wchar_t'. Во всяком случае, широкая поддержка символов в стандарте C несколько порвана. И большинство современных систем используют UTF-8. – Olaf

ответ

5

Вам даже не нужно проверять, использует ли компилятор подписанный или неподписанный тип для широких литералов.

Вы можете просто проверить, если тип широких символьных литералов соответствует вашим ЬурейеЕ:

static_assert(_Generic(L'.', wchar_t : 1, default : 0), "blahblah"); 

Но если вы действительно хотите получить тип знаковость, использовать что-то вроде этого:

static_assert(_Generic(L'.', char : ((char)-1 < 0), signed char : 1, short : 1, int : 1, long : 1, long long : 1, default : 0) == _WIDE_CHAR_IS_SIGNED, "blahblah"); 

И (по предложению @chux) здесь более безопасная версия, которая заставляет ошибку компиляции, если широкий тип символов не соответствует ни одному из стандартных.

#define T(x) signed x : 1, unsigned x : 0 // Makes the code more readable 
static_assert(_Generic(L'.', char : ((char)-1 < 0), T(char), T(short), T(int), T(long), T(long long)) == _WIDE_CHAR_IS_SIGNED, "blahblah"); 
#undef T 
+0

Это опрятно, но я не думаю, что он работает с C99? – user694733

+0

@ user694733 Да, для этого требуется C11, но OP сказал, что C11 в порядке для него. – HolyBlackCat

+0

* sigh * - Когда я начал этот проект, C99 был «текущим» стандартом. C11 дал мне много полезных инструментов, но и многое другое, чтобы реализовать, прежде чем я это сделаю. ;-) Не желая отмечать это, так как @Lundin сначала прокомментировал '_Generic' (о котором я совсем забыл). Если он не ответит, вы получите «зеленый крючок» через пару минут. – DevSolar

 Смежные вопросы

  • Нет связанных вопросов^_^