出于好奇,我研究了std::is_pointer
是如何实现的,并看到了这样的东西(多个重载之一(:
template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;
如果我将其复制并粘贴到代码中并进行编译,则表示constexpr在这里无效。发生了什么?
我们有可能实现像std::is_pointer
和std::is_reference
这样的结构吗?(不是说我会,只是好奇,所以请不要来找我(
MRE与msvc 2019:
template <class _Ty>
inline constexpr bool is_pointer_v<_Ty*> = true;
int main()
{
}
--
Error: error C7568: argument list missing
after assumed function template 'is_pointer_v'
回答标题中的问题:
不,标准库代码不需要遵守用户代码的语言规则。从技术上讲,它甚至不需要在C++中实现,但可以直接集成到编译器中。
然而,实际上,标准库代码总是像用户代码一样由编译器编译,因此它不会使用编译器拒绝用户代码的任何语法构造。然而,它将使用编译器特定的扩展,并保证用户代码通常不应依赖这些扩展。此外,标准中还专门对标准库实现进行了一些保留。
例如,您从标准库实现中显示的代码段不是有效的用户代码,因为_Ty
是用户代码可能不会使用的保留标识符,因为它以下划线开头,后跟大写字母。这样的标识符专门保留给标准库实现。仅出于这个原因,大多数标准库代码将不是有效的用户代码。
您在这里使用的是部分模板专用化。您需要一个完整的模板声明来编译代码,如下所示:
template <class _Ty>
inline constexpr bool is_pointer_v = false;
template <class _Ty>
inline constexpr bool is_pointer_v<_Ty*> = true;
参见此处获取示例代码
为了回答您的问题,STL实现需要编译器实现的特定C++原语来支持所需的API。如果编译器不实现STL的constexpr
版本,就不能实现它
如果没有一些编译器特定的代码和操作系统的基元,就不可能实现完整的STL。这因系统而异(例如,您不能在windows上使用linux的STL实现(。它依赖于未定义的行为,以及许多已知适合特定编译器的优化。
例如,如果没有C++中的UB,就无法实现类型punning(即从float*
转换为int*
并取消引用((请参阅此处和此处(
你必须依赖memcpy,但如果没有UB代码(如果你编写编译器,BTW,这是很好定义的(,这是无法实现的,因为memcpy访问的内存可能不是它声明的初始类型。
然而,你总是可以复制&粘贴系统中的STL代码,它将始终在编译器上正确构建。