libc ++的std :: is_literal_type如何工作?

时间:2018-12-29 14:58:06

标签: c++ std c++17 c++-standard-library libc++

std::is_literal_typestd::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> {};

我写了一个演示:

#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;
}

结果为falsefalse。但是is_literal_type_v<s>的结果是true

有人可以解释std::is_literal_type的工作原理吗?

2 个答案:

答案 0 :(得分:5)

is_literal_type是“神奇的” C ++库。它 不能用当前的语言在C ++中实现(通过静态反射,应该可以,但是最早是C ++ 23)。它是使用特定于编译器的内部工具而不是直接使用C ++来实现的。 _LIBCPP_IS_LITERAL可能是编译器定义的宏(因此,它看起来是未定义的),它表示特定的编译器内部函数。

因此,您实际上不应该过于仔细地研究此类型特征或许多其他类型特征的实现。

我认为未定义_LIBCPP_IS_LITERAL的版本是为了与未公开必需的内部函数的较早版本的编译器兼容。因此,在没有编译器支持的情况下,库实现会尽其所能。

答案 1 :(得分:2)

要添加到@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):确定给定类型是否为文字类型

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

  

__ is_literal_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.

但是,您不应直接使用这些内在函数,因为您可以看到它们不是可移植的。它们是为标准库开发人员定义的。