Как работает libc ++ std :: is_literal_type? - PullRequest
0 голосов
/ 29 декабря 2018

Это та же самая ситуация для std::is_literal_type и std::is_standard_layout.

Реализация std::is_literal_type в libc ++ равна

template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_literal_type
#ifdef _LIBCPP_IS_LITERAL
    : public integral_constant<bool, _LIBCPP_IS_LITERAL(_Tp)>
#else
    : integral_constant<bool, is_scalar<typename remove_all_extents<_Tp>::type>::value ||
                              is_reference<typename remove_all_extents<_Tp>::type>::value>
#endif
    {};

Нет _LIBCPP_IS_LITERAL, поэтомукод будет

template <typename T> struct is_literal_type : integral_constant<bool,
    is_scalar<typename remove_all_extents<T>::type>::value or
    is_reference<typename remove_all_extents<T>::type>::value> {};

Я написал демо:

#include <iostream>

using namespace std;
struct s {
    int a;
    char b;
    long c;
};
int main(int argc, char *argv[]) {
    cout << boolalpha;
    cout << is_scalar_v<typename remove_all_extents<s>::type> << endl;
    cout << is_reference_v<typename remove_all_extents<s>::type> << endl;
}

Результат - false и false.Но результат is_literal_type_v<s> равен true.

Может кто-нибудь объяснить, как работает std::is_literal_type?

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Чтобы добавить к предыдущему ответу @NicolBolas: вероятно, неправильно, что _LIBCPP_IS_LITERAL не установлен.Посмотрите на __config.h:

#if defined(_LIBCPP_COMPILER_CLANG)

[...]

#if __has_feature(is_literal)
#define _LIBCPP_IS_LITERAL(T) __is_literal(T)
#endif

[...]

#elif defined(_LIBCPP_COMPILER_GCC)

[...]

#if _GNUC_VER >= 407
[...]
#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T)
[...]
#endif

. Поэтому макрос будет установлен, если вы компилируете с достаточно недавним Clang или GCC, и в любом случае он будет использовать встроенную компилятор.__is_literal для Clang или __is_literal_type для GCC.

Оба встроенных документа задокументированы:

From https://clang.llvm.org/docs/LanguageExtensions.html:

__ is_literal (тип): определяет, является лиданный тип является литеральным типом

С https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:

__ is_literal_type (type)

If type is a literal type ([basic.types]) the trait is true, else it is false. Requires: type shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.

Вы не должныиспользуйте эти встроенные функции напрямую, потому что, как вы можете видеть, они не переносимы.Они определены для разработчиков стандартной библиотеки.

0 голосов
/ 29 декабря 2018

is_literal_type - «волшебная» библиотека C ++.Он не может быть реализован в C ++ в том виде, в каком он существует в настоящее время (со статическим отражением это должно быть возможно, но это C ++ 23 в ближайшее время).Он реализуется с помощью встроенных инструментов, специфичных для компилятора, а не с помощью C ++ напрямую._LIBCPP_IS_LITERAL - это, вероятно, макрос, определенный компилятором (следовательно, он выглядит неопределенным), который представляет этот конкретный встроенный компилятор.

Таким образом, вам действительно не следует слишком внимательно присматриваться к реализации этого или многих изчерты другого типа.

Я предполагаю, что версия, в которой _LIBCPP_IS_LITERAL не определена, предназначена для совместимости со старыми версиями компилятора, которые не предоставили необходимую встроенную функцию.Таким образом, реализация библиотеки делает все возможное без поддержки компилятора.

...