libc++ 的 std::is_literal_type 是如何工作的?
How does libc++'s std::is_literal_type work?
这与 std::is_literal_type
和 std::is_standard_layout
的情况相同。
libc++中std::is_literal_type
的实现是
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> {};
我写了一个demo:
#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
是如何工作的?
is_literal_type
是一个 "magic" C++ 库。它 不能 在 C++ 中作为当前语言实现(使用静态反射,它应该是可能的,但那是最快的 C++23)。它是通过使用特定于编译器的内部工具来实现的,而不是直接使用 C++。 _LIBCPP_IS_LITERAL
可能是编译器定义的宏(因此它看起来未定义),它表示特定的编译器内在。
因此,您真的不应该太仔细地研究这个或许多其他类型特征的实现。
我认为未定义 _LIBCPP_IS_LITERAL
的版本是为了与未公开必要内在函数的旧版本编译器兼容。因此,库实现在没有编译器支持的情况下尽其所能。
添加@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。
两个内在函数都有记录:
来自https://clang.llvm.org/docs/LanguageExtensions.html:
__is_literal(type): Determines whether the given type is a literal type
来自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.
不过您不应该直接使用这些内部函数,因为如您所见,它们不可移植。它们是为标准库开发人员定义的。
这与 std::is_literal_type
和 std::is_standard_layout
的情况相同。
libc++中std::is_literal_type
的实现是
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> {};
我写了一个demo:
#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
是如何工作的?
is_literal_type
是一个 "magic" C++ 库。它 不能 在 C++ 中作为当前语言实现(使用静态反射,它应该是可能的,但那是最快的 C++23)。它是通过使用特定于编译器的内部工具来实现的,而不是直接使用 C++。 _LIBCPP_IS_LITERAL
可能是编译器定义的宏(因此它看起来未定义),它表示特定的编译器内在。
因此,您真的不应该太仔细地研究这个或许多其他类型特征的实现。
我认为未定义 _LIBCPP_IS_LITERAL
的版本是为了与未公开必要内在函数的旧版本编译器兼容。因此,库实现在没有编译器支持的情况下尽其所能。
添加@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。
两个内在函数都有记录:
来自https://clang.llvm.org/docs/LanguageExtensions.html:
__is_literal(type): Determines whether the given type is a literal type
来自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.
不过您不应该直接使用这些内部函数,因为如您所见,它们不可移植。它们是为标准库开发人员定义的。