strong<T, Tag> ‐ prevent accidental mixing of semantically different uses of the same underlying type. Known as "newtype" in some languages. C++20. Default‐construction value‐initializes T, even if it's a primitive type.
Synopsis
Declared in <folly/lang/Strong.h>
template<
typename T,
typename>
class strong;
Description
The tag type should be the name of your derived type. This guarantees that different strong `T`s are not interchangeable.
The std::hash, fmt::format, and operator<<(ostream&) implementations rely on this convention, so if you see failures in those, check your tag. You can customize the output per‐type, see CustomOutput in the test.
It is often OK to allow implicit construction from the underlying type. We strongly recommend using concepts to limit undesired conversions:
struct UserId : public strong<uint64_t, UserId> { using strong<uint64_t, UserId>::strong; // Prohibit risky signed‐unsigned & float‐int conversions. // Callers will want to suffix integer literals with u. /* implicit */ UserId(std::unsigned_integral auto n) : strong{n} {} };
UserId uid{123u}; // OK, explicit construction UserId uid = 123u; // OK, implicit conversion UserId uid{123}; // Warning: narrowing conversion UserId uid = 123; // Error: no viable conversion
For ease of use, even without an implicit constructor, your strong type will be comparable with the underlying type.
Type Aliases
Name |
Description |
The wrapped underlying type |
Member Functions
Name |
Description |
|
Constructors |
|
|
Explicitly convert to a mutable lvalue reference to the underlying value. |
|
Explicitly convert to an rvalue reference to the underlying value. |
|
Explicitly convert to a const lvalue reference to the underlying value. |
|
Explicitly convert to a const rvalue reference to the underlying value. |
Friends
Name |
Description |
Three‐way‐compare a |
|
Equality‐compare a |
|
Three‐way‐compare two |
|
Equality‐compare two |
Derived Classes
Name |
Description |
|
Created with MrDocs