【问题标题】:How does libc++'s std::is_literal_type work?libc++ 的 std::is_literal_type 是如何工作的?
【发布时间】:2018-12-29 14:58:05
【问题描述】:

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

结果是falsefalse。但是is_literal_type_v&lt;s&gt; 的结果是true

谁能解释std::is_literal_type的工作原理?

【问题讨论】:

  • 这并不能解决问题,但我发现在修改代码以保持原始格式直到我确定它有效之前它很有帮助;这样可以更轻松地确保没有无意的更改。你的是正确的,但如果格式没有改变会更容易看到。

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


【解决方案1】:

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

因此,您真的不应该过分关注这个或许多其他类型特征的实现。

我想未定义 _LIBCPP_IS_LITERAL 的版本是为了与未公开必要内在函数的旧版本编译器兼容。所以库实现在没有编译器支持的情况下会做到最好。

【讨论】:

  • 为了完整性:修改后的版本得到错误答案的原因仅仅是它(必然)不完整。
【解决方案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.

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 2013-06-15
    • 2012-12-15
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多