Navigation
API > API/Runtime > API/Runtime/Core
Implementation
TAdderRef and TAdderReserverRef are type-erasing adapters that allow a function to add to (and reserve) a container without the function knowing about the specific type of the container. This allows the container and allocator to vary without having to change the function signature or make it a template.
Example:
void AddThree(TAdderRef
void AddZeroToFour(TAdderReserverRef
TArray
AddThree(Arr); // Arr == { 3 } AddThree(Set); // Set == { 3 } AddZeroToFour(Arr); // Arr == { 3, 0, 1, 2, 3, 4 } AddZeroToFour(Set); // Set == { 3, 0, 1, 2, 4 } - only contains one 3 because it's a set
The inline allocation policy allocates up to a specified number of elements in the same allocation as the container. Any allocation needed beyond that causes all data to be moved into an indirect allocation. It always uses DEFAULT_ALIGNMENT.
Facilities to allow types to have an intrusive invalid state which can act as TOptional's 'unset' state, saving space. A class in such a state will only ever be compared against FIntrusiveUnsetOptionalState or destructed.
A class should implement a constructor taking FIntrusiveUnsetOptionalState, and an equality comparison operator against FIntrusiveUnsetOptionalState, which will put a class instance into the 'unset' state (in the case of the constructor) and allow testing of its unset state.
A public constexpr static data member of type bool called bHasIntrusiveUnsetOptionalState should be defined and set to true. There must also be a public typedef/alias called IntrusiveUnsetOptionalStateType and set to the type itself. This enables the optimization of this type within TOptional.
These functions should be public - regular user code will not be able to call them as they will not be able to construct an FIntrusiveUnsetOptionalState object to pass.
Example:
struct FMyType { // This static member should be constexpr, public and equal to true. static constexpr bool bHasIntrusiveUnsetOptionalState = true;
explicit FMyType(int32 InIndex) { // Validate class invariant. check(InIndex >= 0);
Index = InIndex; }
// This constructor will only ever be called by TOptional
// This comparison function will only ever be called by TOptional to check if the // object is in the 'unset' state. It does not need to be commutative like most // comparison operators, nor is an operator!= necessary. bool operator==(FIntrusiveUnsetOptionalState) const { return Index == -1; }
private: // Non-negative indices are part of the class invariant. int32 Index; };
INTERNAL USE ONLY Do not use this type. Its internal use case is for in-place construction of non-default-constructible types during serialization.
Module implementation boilerplate for regular modules.
This macro is used to expose a module's main class to the rest of the engine. You must use this macro in one of your modules C++ modules, in order for the 'InitializeModule' function to be declared in such a way that the engine can find it. Also, this macro will handle the case where a module is statically linked with the engine instead of dynamically loaded.
This macro is intended for modules that do NOT contain gameplay code. If your module does contain game classes, use IMPLEMENT_GAME_MODULE instead.
Usage: IMPLEMENT_MODULE(
Utilities for concepts checks.
In this case, a successful concept check means that a given C++ expression is well-formed. No guarantees are given about the correctness, behavior or complexity of the runtime behaviour of that expression.
Concepts are structs with a rather unusual definition:
struct CConcept { template <[...concept parameters...]> auto Requires([...placeholder variables...]) -> decltype( [...expression(s) to test the validity of...] ); };
The prefix C is reserved for concepts, and concepts should be directly named as an adjective and not like a predicate, i.e.: CEqualityComparable - good CIsComparable - bad CHasEqualsOperator - bad
Concepts can be checked using the TModels_V trait or TModels traits class:
TModels_V
The arguments are forwarded to the template parameters of the concept's Requires() function, which will attempt to compile the expression(s) in the return value, and SFINAE is utilized to test whether that succeeded.
The placeholders are simply any variable declarations you need to write your expression(s).
Note that 'legal C++' doesn't necessarily mean that the expression will compile when used. The concept check only tests that the syntax is valid. Instantiation of function template bodies may still fail. See the CContainerLvalueAddable example below.
UE::Overload allows the combining of multiple invocables into a single object where they are overloaded.
Example:
TTuple
Warning:
All of the invocables' captured state is copied into the result. If the same capture is present in multiple callables, e.g. Capture1 above, the overload object will contain multiple copies of that capture.
Another pitfall is to capture-by-move multiple times - only one of the captures will be valid:
FStringName = ...; Visit( UE::Overload( Name = MoveTemp(Name) { Val1.DoThing1(Name); // Either this... }, Name = MoveTemp(Name) { Val2.DoThing2(Name); // ... or this will be an empty name. } ), Variant );
If these are problems, consider writing a bespoke struct with one copy of the capture with multiple operator() overloads.
| Name | UE::Core::Private::ENullTerminatedString |
| Type | enum |
| Header File | /Engine/Source/Runtime/Core/Public/Containers/StringConv.h |
| Include Path | #include "Containers/StringConv.h" |
Syntax
namespace UE
{
namespace Core
{
namespace Private
{
enum ENullTerminatedString
{
No = 0,
Yes = 1,
}
}
}
}
Values
| Name | Remarks |
|---|---|
| No | |
| Yes |