Just out of curiosity, I looked at how std::is_pointer
is implemented and saw stuff like this (one of multiple overloads):
template <class _Ty>
_INLINE_VAR constexpr bool is_pointer_v<_Ty*> = true;
which if I copy and paste into my code and compile says constexpr is not valid here. What is happening?
Is it possible to implement structs like std::is_pointer
and std::is_reference
by us? (Not that I would, just curious so please don't come at me)
MRE with 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'
CodePudding user response:
To answer the question in the title:
No, standard library code does not need to adhere to the language rules for user code. Technically it doesn't even need to be implemented in C , but could e.g. be directly integrated into the compiler.
However, practically the standard library code is always compiled by the compiler just as user code is, so it will not use any syntax constructs that the compiler would reject for user code. It will however use compiler-specific extensions and guarantees that user code should not generally rely on. And there are also some reservations made specifically to the standard library implementation in the standard.
For example, the snippet you are showing from the standard library implementation is not valid user code, because _Ty
is a reserved identifier that may not be used by user code, because it starts with an underscore followed by an uppercase letter. Such identifiers are specifically reserved to the standard library implementation. For this reason alone most standard library code will not be valid user code.
CodePudding user response:
You are using a partial template specialization here. You need a complete declaration of the template to get that code to compile, like this:
template <class _Ty>
inline constexpr bool is_pointer_v = false;
template <class _Ty>
inline constexpr bool is_pointer_v<_Ty*> = true;
To answer your questions, the STL implementation requires specific C primitives that the compiler implements to support the required API. You can't have a constexpr
version of the STL if the compiler does not implement it.
It's not possible to implement the complete STL without some compiler specifics code and the operating system's primitives. This is different from system to system (you can't use the STL implementation of linux on windows for example). It relies on undefined behavior, and many optimization which are known to be right for that specific compiler.
For example, you can't implement type punning (i.e converting from float*
to int*
and dereferencing) without UB in C (see here and here)
You have to rely on memcpy, but that can't be implemented without UB code (that is well defined if you write the compiler, BTW), since memcpy is accessing the memory likely not in the initial type that it's declared.
Yet, you can always copy & paste the STL code from your system and it'll always build correctly on your compiler.