2008-11-11 10 views
28

У меня есть код низкоуровневой сериализации, который является шаблоном, и я должен знать, что системная консистенция в compiletime явно (потому что шаблоны специализируются на основе сущности системы).Есть ли способ сделать утверждение времени компиляции в стиле C++ для определения конечности машины?

Прямо сейчас у меня есть заголовок с определением какой-то платформы, но я бы предпочел каким-то образом сделать утверждения о контенте с помощью некоторого шаблонного теста (например, static_assert или boost_if). Причина, по которой мой код должен быть скомпилирован и запущен на широком спектре машин, многих специализированных поставщиков и, вероятно, устройств, которые не существуют в 2008 году, поэтому я не могу догадаться, что может понадобиться для этого года заголовка по дороге. А так как кодовая база имеет ожидаемый срок службы около 10 лет. Поэтому я не могу следовать коду навсегда.

Надеюсь, это делает мою ситуацию ясной.

Знаете ли вы, что кто-нибудь знает тест времени компиляции, который может определять сущность, не полагаясь на специфику поставщика?

ответ

18

Если вы используете Autoconf, вы можете использовать AC_C_BIGENDIAN макрос, который достаточно гарантированно работать (установив WORDS_BIGENDIAN определяют по умолчанию)

попеременно, вы можете попробовать что-то вроде следующего (взято из Autoconf) чтобы получить тест, который, вероятно, будет оптимизирован далеко (НКА, по крайней мере, удаляет другую ветвь)

int is_big_endian() 
{ 
    union { 
     long int l; 
     char c[sizeof (long int)]; 
    } u; 

    u.l = 1; 

    if (u.c[sizeof(long int)-1] == 1) 
    { 
     return 1; 
    } 
    else 
     return 0; 
} 
5

Хм, это интересный вопрос. Моя ставка заключается в том, что это невозможно. Я думаю, вам нужно продолжать использовать макросы и переходить с BOOST_STATIC_ASSERT(!BIG_ENDIAN);, или static_assert в C++ 0x. Причина, по которой я думаю, это потому, что endian'nes - это свойство, если ваша среда исполнения. Однако static_assert учитывается во время компиляции.

Предлагаю ознакомиться с кодом нового GNU gold ELF-линкер. Ян Лэнс Тейлор (Ian Lance Taylor), ее автор, использовал шаблоны для выбора правильной сущности во время компиляции, чтобы обеспечить оптимальную производительность во время выполнения. Он явно создает все возможные континенты, так что у него все еще есть отдельная компиляция (не все шаблоны в заголовках) определения шаблона и объявления. Его код отличный.

+0

Да, я не был в состоянии понять это сам, и, как вы говорите, что не может быть даже возможно , Но я видел невозможное ранее для других ситуаций ... так что, может быть, может быть, кто-то может придумать отличную идею здесь :) – 2008-11-11 06:36:06

+0

Почему это не может работать: `#define IS_LITTLE_ENDIAN char (0x00ff)`. Это решение немного вдохновлено ответом @ MichaelBurr. Он хорошо работает с шаблонами, а также [demo] (http://ideone.com/JAS7mO). Предположим, что `uint8_t` вместо` char` будет точным. – iammilind 2016-02-08 12:43:48

+1

@iamm Я не думаю, что можно построить битпаттерны в C или C++. Вы создаете значение 255 и затем передаете его в char. Даже если C разрешил вам указывать бит-представление, вы все же можете убедить компилятор интерпретировать этот битпаттерн как содержимое памяти и загружать его в регистр, а не иметь его как непосредственное значение. Для исключительных регистров, таких как усечение и нулевое расширение, endianness не имеет отношения к IIRC. – 2016-02-08 18:02:27

18

Существует нет портативного способа сделать это во время компиляции, лучше всего использовать Boostendian macros или эмулировать методы, которые они используют.