According to What are the reasons that extending the std namespace is considered undefined behavior?, adding anything to namespace std is Undefined Behavior, with some exceptions carved out, such as specializing std::hash. The primary reason for this is to allow the namespace to grow in future standards without risking collisions with user-written code.
Therefore, is it allowed to backport a specific feature to older standards, provided there are no language restrictions forbidding it? It clearly cannot collide with something that would be defined later.
As a concrete example, let's take:
namespace backport {
#if __cplusplus < 202002L
template <typename T>
struct type_identity { using type = T; };
#else
using ::std::type_identity<T>;
#endif
}
static_assert(std::is_same<backport::type_identity<int>::type, int>::value, "");
This safely works in all of C++11 up to C++26 (C++03 does not have <type_traits>). Could I also safely write it without the extra namespace?
#if __cplusplus < 202002L
namespace std {
template <typename T>
struct type_identity { using type = T; };
}
#endif
static_assert(std::is_same<std::type_identity<int>::type, int>::value, "");
std(unless explicitly allowed) is UB - you have UB here.