Можно ли использовать std :: endian, если он доступен, в противном случае сделать что-то еще? - PullRequest
8 голосов
/ 09 апреля 2020

Начиная с C ++ 20, мы можем иметь:

constexpr bool is_little_endian = std::endian::native == std::endian::little;

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

Может быть, код будет выглядеть так:

template<bool b = std_endian_exists_v> constexpr bool is_little_endian;
template<> constexpr bool is_little_endian<true> = std::endian::native == std::endian::little;
template<> constexpr bool is_little_endian<false> = runtime_detection();

Я знаю, что тестирование __cplusplus с помощью препроцессора возможно, однако фаза компиляторов в C ++ 20 поддерживает различные этапы, так что это не является надежным индикатором в любом направлении.

1 Ответ

7 голосов
/ 09 апреля 2020

Мне известно, что тестирование __cplusplus с помощью препроцессора возможно, однако фаза компиляторов в C ++ 20 поддерживается на разных этапах, так что это не является надежным индикатором в обоих направлениях.

Верно! Фактически, именно поэтому у нас теперь есть совершенно новый метод определения поддержки функций для компиляторов, которые находятся на разных этапах выпуска: макросы тестирования возможностей! Если вы посмотрите на SD-FeatureTest , то есть большие таблицы макросов, соответствующие каждому языку и библиотечной функции, принятой в стандарте, где каждый макрос будет определен с указанным значением после того, как функция будет принята.

В вашем конкретном c случае вы хотите __cpp_lib_endian.

Теперь проблема с макросами библиотеки заключается в том, что мы начали добавлять их до того, как мы добавил место для их размещения - что будет <version>. Если вы используете компилятор, который имеет <version> (который будет g cc 9+, clang 7+ с libc ++, и я не знаю о MSV C), вы можете просто включить это. Но это может и не произойти, поэтому вам также может потребоваться включить правильный заголовок (в данном случае <bit>).

#if __has_include(<bit>)
#  include <bit>
#  ifdef __cpp_lib_endian
#    define HAS_ENDIAN 1
#  endif
#endif

#ifdef HAS_ENDIAN
constexpr bool is_little_endian = std::endian::native == std::endian::little;
#else
constexpr bool is_little_endian = /* ... figure it out ... */;
#endif

Хотя может быть лучше сделать:

#ifdef HAS_ENDIAN
using my_endian = std::endian;
#else
enum class my_endian {
   // copy some existing implementation
};
#endif

constexpr bool is_little_endian = my_endian::native == my_endian::little;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...