【问题标题】:Why some C++ feature test macros require header inclusion?为什么某些 C++ 功能测试宏需要包含标头?
【发布时间】:2021-10-15 23:35:23
【问题描述】:

某些 C++ feature test macros(例如 __cpp_lib_three_way_comparison)需要包含标头(例如 <compare>)来测试它们。

这似乎很倒退,例如也许我只想在我知道编译器支持头文件时才包含头文件(更准确地说是它使用的编译器+标准库 impl),例如假设我有my_fancy_string_view,如果std::string_view 可用,我想将其键入std::string_view,但要检测std::string_view 是否可用,我需要包含<string_view>...

这只是此功能设计中的“错误/糟糕”,还是编译器未预定义所有功能测试宏是否有充分的理由?我的猜测是可能允许混合 STL 实现,例如clang 在某些平台上使用 gcc 的 std lib 实现,但我再次假设编译器知道他们使用哪些 std lib 实现,因此他们可以调整预定义的宏。

我知道 <version> 标头存在,但这对我没有帮助,因为它仅在 C++20 中添加。 当我的基线是 C++20 时,它可能会在 10 多年后变得很好,但现在它不是那么有用。
此外,添加此标头的事实可能表明实际上要求“重”包含是一个错误,但我想就此获得专家意见。

附: This 是添加了<version> 的提案,但它非常小,所以没有细节......

【问题讨论】:

  • C++17 有__has_include 来检查头文件是否存在。
  • 您希望编译器预定义标准库中的所有功能测试宏吗?其中一些功能将基于编译器版本?对于那些库实现依赖于语言特性的库特性(例如,三路比较),这将如何工作?
  • 仅当 C++ >= 20 或 <ciso646> (或者 iso646.h )时才包含 <version> 对于早期版本可能是一个选项。
  • 编译器知道它会使用什么标准库,对吧? 实际上,不知道。例如,请参阅stackoverflow.com/questions/14972425/…
  • 当然,但我不认为编译器“知道”libc++libstdc++ 之间的所有详细差异。那要求太高了。此外,库开发人员希望能够独立于编译器开发人员进行更改。

标签: c++ c++20


【解决方案1】:

但要检测 std::string_view 是否可用,我需要包含 ...

不,您必须先使用__has_include(&lt;string_view&gt;)

库功能由标题定义,因为由标题定义。在大多数情况下,编译器在编译之前无法知道标头的内容。

是的,标准库的许多部分都可以跨编译器使用。虽然某些组件是特定于编译器/平台的,但可以在不依赖平台/编译器细节的情况下实现许多标准库。标准库,或者至少其中的大部分,可以独立于它所挂钩的编译器进行更新。

【讨论】:

  • “可以”我觉得有点弱? libc++ 和 libstdc++ 可以并且确实使用完全相同的编译器,并且通常实现不同的功能集。 “一些标准库”可能是一个更强有力的陈述(因为并非所有标准库都支持多个编译器)
【解决方案2】:

从 cmets 开始,这里要讨论的一个问题是,您不希望编译器必须确切知道库实现支持和不支持哪些功能它使用。

这样做需要在每次更新库时都对编译器进行更改,而这很快就会变得难以管理。

换句话说,库的工作是通知使用它的代码它支持哪些功能,而这只能通过库的头文件来完成。

【讨论】:

  • 作为一个具体问题,一些编译器支持不止一组标准头文件。这些标准头文件可能实现了不同的功能
猜你喜欢
  • 2020-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多