DXX-Rebirth requires a compiler that implements the C++17 standard. A fully conforming compiler is recommended, but some omissions can be handled by SConf tests that enable a fallback to emulate the feature.
DXX-Rebirth code uses C++11 and C++14 features present in >=clang-9.0 and >=gcc-7.5. Some of these features are probed in the SConf tests so that an error can be reported if the feature is missing. However, since these are considered the minimum supported compiler versions, and existing SConf tests reject older compilers, some C++14 features that are new in gcc-7.5 may be used without a corresponding test in SConf.
* [`std::make_unique`][cppr:cpp/memory/unique_ptr/make_unique] is a convenience utility function for constructing `std::unique_ptr` with a managed value.
DXX-Rebirth code may use C++11 or C++14 features not present in the minimum supported compiler if the feature can be emulated easily (C++11: [inheriting constructors][cppr:cpp/language/using_declaration], [Range-based for][cppr:cpp/language/range-for]) or if the feature can be removed by a macro and the removal does not change the correctness of the program (C++11: [rvalue-qualified member methods][scppr:rvalue method]).
* [Inheriting constructors][cppr:cpp/language/using_declaration] are wrapped by the macro `DXX_INHERIT_CONSTRUCTORS`.
If inherited constructors are supported, then `DXX_INHERIT_CONSTRUCTORS` expands to a `using` declaration.
If inherited constructors are not supported, then `DXX_INHERIT_CONSTRUCTORS` defines a [variadic template][cppr:cpp/language/parameter_pack] constructor to forward arguments to the base class.
* [Range-based for][cppr:cpp/language/range-for] is wrapped by the macro `range_for`.
This feature is present in the current minimum supported compiler versions.
It was first used when >=gcc-4.5 was the minimum.
Use of the `range_for` macro continues because it improves readability.
### Preprocessed out if absent
* [Reference-qualified methods][scppr:rvalue method] check that an rvalue which may or may not hold a valid pointer is not used in a context where the caller assumes the rvalue holds a valid pointer.
When the rvalue may or may not hold a valid pointer, it must be saved to an lvalue, tested for a valid pointer, and used only if a valid pointer is found.