EtcPal  0.4.1
ETC Platform Abstraction Layer (EtcPal)
View other versions:
OpaqueId< IdType, ValueType, InvalidValue > Class Template Reference

Overview

template<class IdType, class ValueType, ValueType InvalidValue>
class etcpal::OpaqueId< IdType, ValueType, InvalidValue >

A strongly-typed ID with arbitrary internal representation.

A typical coding pattern uses handles to represent resources stored elsewhere by a module. The handles are usually some integer type, given another name by a type definition, e.g.:

using FooHandle = int;
Foo GetFoo(FooHandle handle);

Unfortunately, this is not as type-safe as it could be. One would expect that handles cannot be mixed with other integers or magic numbers:

int regular_ol_number = 12;
GetFoo(regular_ol_number);
GetFoo(42);

Although handles are typically meant to be treated as opaque (and thus should not be mixable with regular numbers), the block above will compile without warnings.

This can be avoided using the OpaqueId class. Usage is as follows:

struct FooHandleType {};
using FooHandle = etcpal::OpaqueId<FooHandleType, int, -1>;
Foo GetFoo(FooHandle handle);
int regular_ol_number = 12;
GetFoo(regular_ol_number); // Error
GetFoo(42); // Error
GetFoo(FooHandle(42)); // No error
FooHandle foo_handle(42);
if (foo_handle == 42) // Error
{
// ...
}
if (foo_handle.value() == 42) // No error
{
// ...
}
struct BarHandleType {};
using BarHandle = etcpal::OpaqueId<BarHandleType, int, -1>;
BarHandle bar_handle(42);
if (bar_handle == foo_handle) // Error
{
// ...
}
A strongly-typed ID with arbitrary internal representation.
Definition: opaque_id.h:118

When using the OpaqueId type, errors from mixing numbers with opaque handles are avoided. Each distinct specialization of an OpaqueId requires a new struct or class to be defined. This struct/class is typically empty and its only use is to serve as a distinct type such that OpaqueIds used for different purposes cannot be mixed with each other.

The underlying type for an OpaqueId follows the template rules for a non-type template parameter, since an "invalid" value must be passed as a template parameter when specializing OpaqueId. This means that in pre-C++20 environments, the underlying type can pretty much only be an integral or enumeration type. In practice, it is almost always an integer type.

OpaqueIds also have the concept of an invalid value, which is what a default-constructed OpaqueId contains.

FooHandle handle;
if (!handle) // Evaluation in boolean predicate OK
{
// This block will be executed
}
EXPECT_FALSE(handle.IsValid());
EXPECT_EQ(handle, FooHandle::Invalid());

Public Member Functions

constexpr OpaqueId (ValueType value)
 Explicitly create a valid ID based on a value.
 
constexpr ValueType value () const
 Get the underlying value from an ID.
 
constexpr bool IsValid () const
 Explicitly determine whether an ID is valid.
 
constexpr operator bool () const
 Determine whether an ID is valid by testing as a boolean predicate. More...
 
constexpr bool operator! () const
 Determine whether an ID is not valid.
 
ETCPAL_CONSTEXPR_14 void SetValue (const ValueType &new_value)
 Set a new underlying value for an ID. More...
 
ETCPAL_CONSTEXPR_14 void Clear ()
 Clear any valid value from an ID and set it back to the invalid value. More...
 

Static Public Member Functions

static constexpr OpaqueId Invalid ()
 Explicitly create an invalid ID. More...
 

Member Function Documentation

◆ Clear()

Clear any valid value from an ID and set it back to the invalid value.

Postcondition
value.IsValid() will return false.

◆ Invalid()

constexpr OpaqueId< IdType, ValueType, InvalidValue > Invalid
staticconstexpr

Explicitly create an invalid ID.

Example:

using FooId = etcpal::OpaqueId<FooIdType, int, -1>;
auto invalid_id = FooId::Invalid();
EXPECT_FALSE(invalid_id.IsValid());

◆ operator bool()

constexpr operator bool
explicitconstexpr

Determine whether an ID is valid by testing as a boolean predicate.

Example:

if (id)
{
// Do things if id is valid
}
else
{
// Do things if id is invalid
}

◆ SetValue()

ETCPAL_CONSTEXPR_14_OR_INLINE void SetValue ( const ValueType &  new_value)

Set a new underlying value for an ID.

Parameters
new_valueThe new value to set.

The documentation for this class was generated from the following file: