cxxomfort
rel.20211024
Simple backports for C++ - https://ryan.gulix.cl/fossil.cgi/cxxomfort/
|
cxxomfort backports for <type_traits>
Interfaces provided by this header include:
is_lvalue_reference
- brought to C++03 as a mirror to is_reference
(C++11).is_rvalue_reference
- identifies rvalue references (always false in C++03).
std::decay "decay<T>" - perform implicit decay on a type.
cxxomfort::cxxostd::common_type "common_type" - obtains the type that a list of types decays or converts to (see note below).std::underlying_type
"underlying_type<Enum>" - underlying integral for an enum
.is_trivial
, is_literal_type
(C++11).is_null_pointer
(C++14) - identifies std::nullptr_t
.void_t
, make_void
- generic, type-absorbing void
transformations (C++17).cxxomfort::cxxostd::bool_constant
"std::bool_constant" (C++17).
remove_cvref (C++20).Non-backport interfaces (cxxomfort::fix
):
to_value()
overloads to check the value of a type_trait object: see type_traits accessors .to_bool()
for false_type
, true_type
(see above).common_type
- implements "variadic" common_type
in MSVC 2010, MSVC 2012 where it has issues, or refers to std::common_type
otherwise.The implementation of every type_traits helper utility in Cxxomfort depends on what is detected about the capabilities of the compiler.
Several type traits refer to information that can not be computed by the language but has to be provided by "compiler magic". Usually those traits refer to a compiler intrinsic with a similar name: is_pod<T>
refers to something like __is_pod(T)
provided magically by the compiler.
If possible, cxxomfort will supplement a missing type_trait with one invoking the corresponding intrinsic if that is found. An example is __is_final
in MSVC.
Other type traits refer to information that can often times be computed in the version of the Standards where they appear, but for which intrinsics with incomplete or different implementation was found in earlier Standards. An example is the triviality traits (is_trivially_copy_constructible
, etc) which pre-C++11 would rely on an intrinsic (like __has_trivial_copy
) that has different meaning and capabilities.
In those cases, cxxomfort tries to provide a barebones implementation that invokes the intrinsic when found; if not found, or if the behaviour is too different, a simpler approximation that at least provides no false positives is implemented instead. For example, in pre-C++11 compilers with the __has_trivial_copy(T)
intrinsic is_trivially_copy_constructible
uses it, but in certain patological cases or if not found, is_trivially_copy_constructible
will instead check if the type applies for is_scalar
.
A quick summary of the simpler approximations, based on information from cppreference, is provided here:
Type Trait | Intrinsic if found | Alternative Approximation |
---|---|---|
is_trivially_xxx_constructible | __has_trivial_xxx, __has_trivial_constructor | is_fundamental |
is_trivially_copy_assignable | __has_trivial_assign | is_fundamental |
is_trivially_destructible | __has_trivial_destructor | is_fundamental && !is_void |
is_nothrow_xxx_constructible | __has_nothrow_xxx | is_scalar |
is_standard_layout | __is_standard_layout | is_scalar |
is_trivial | __is_trivial | is_scalar || (is_class && is_trivially_default_constructible && is_trivially_default_copyable && is_trivially_destructible) |
is_literal_type | __is_literal_type | is_scalar || is_reference |
has_virtual_destructor | __has_virtual_destructor | false_type |
is_final | __is_final | false_type |
Other type traits refer to information that changes meaning between versions of the Standard and that is not easily, or at all, computable without "compiler magic". In those cases, cxxomfort simply does not provide a supplement. An example is C++17's is_aggregate
, as the definition of an Aggregate has changed in every version of the Standard and even if a __is_aggregate(T)
was found, it would only give a proper meaning for the exact compiler and Standards version where it was found.
cxxomfort provides for std::integral_constant
and its related types, including the various type traits implemented via it, the following special functions to check the value of an integral_constant
or derived object generically. This is intended to supplement the implicit conversion operator and the .value() member introduced in later versions of the Standard.
is_empty
and is_pod
. If they are not available, the library does not compile correctly.__typeof__
support, common_type
may not resolve correctly.underlying_type
may not resolve correctly.