Sane C++ Libraries
C++ Platform Abstraction Libraries
Foundation Extra

🟥 Foundation types built using some simple C++ meta-programming

Features

Classes

Class Description
SC::TaggedUnion Type safe union with an enum type, where each type has an associated enum value.
SC::TaggedMap Map of SC::TaggedUnion, where the key is TaggedUnion enumeration value.

TaggedUnion

Type safe union with an enum type, where each type has an associated enum value.

Template Parameters
Unionwith FieldTypes = TypeList<TaggedType<EnumType, EnumValue, Type>, ...>

Example:

namespace SC
{
struct TaggedUnionTest;
// Create an arbitrary enumeration with some values
enum TestType
{
TypeString = 10,
TypeInt = 110,
};
// Create the union definition containing a FieldTypes nested type
struct TestUnion
{
// Helper to save some typing
template <TestType E, typename T>
using Tag = TaggedType<TestType, E, T>;
// FieldsTypes MUST be defined to be a TypeList of TaggedType(s)
using FieldsTypes = TypeTraits::TypeList< // List all TargetType associations
Tag<TypeString, String>, // Associate TypeString with String
Tag<TypeInt, int>>; // Associate TypeInt with init
};
void taggedUnionUsageSnippet(Console& console)
{
// Create the tagged union on the TestUnion definition
TaggedUnion<TestUnion> test; // default initialized to first type (String)
// Access / Change type
String* ptr = test.field<TypeString>();
if (ptr) // If TypeString is not active type, ptr will be == nullptr
{
*ptr = "SomeValue";
}
test.changeTo<TypeInt>() = 2; // Change active type to TypeInt (compile time known)
// Switch on currently active type (TypeInt)
switch (test.getType())
{
case TypeString: console.print("String = {}", *test.field<TypeString>()); break;
case TypeInt: console.print("Int = {}", *test.field<TypeInt>()); break;
}
// Set current active type at runtime back to TypeString
test.setType(TypeString);
*test.field<TypeString>() = "Some new string";
}
} // namespace SC

TaggedMap

Map of SC::TaggedUnion, where the key is TaggedUnion enumeration value.

Template Parameters
TypeEnumeration type used
Unionwith FieldTypes = TypeList<TaggedType<EnumType, EnumValue, Type>, ...>

Example:

namespace SC
{
// Create an arbitrary enumeration with some values
struct Compile
{
enum Type
{
libraryPath = 10,
enableRTTI = 110,
};
};
// Create the union definition containing a FieldTypes nested type
struct CompileFlags
{
// Helper to save some typing
template <Compile::Type E, typename T>
using Tag = TaggedType<Compile::Type, E, T>;
// FieldsTypes MUST be defined to be a TypeList of TaggedType(s)
using FieldsTypes = TypeTraits::TypeList< // List all associations between type and enumeration
Tag<Compile::libraryPath, String>, // Associate Compile::libraryPath with String
Tag<Compile::enableRTTI, bool>>; // Associate Compile::enableRTTI with bool type
using Union = TaggedUnion<CompileFlags>;
};
} // namespace SC
void SC::TaggedMapTest::basic()
{
TaggedMap<Compile::Type, CompileFlags::Union> taggedMap;
SC_TEST_EXPECT(taggedMap.get<Compile::libraryPath>() == nullptr);
*taggedMap.getOrCreate<Compile::libraryPath>() = "My String";
SC_TEST_EXPECT(*taggedMap.get<Compile::libraryPath>() == "My String");
SC_TEST_EXPECT(taggedMap.get<Compile::enableRTTI>() == nullptr);
*taggedMap.getOrCreate<Compile::enableRTTI>() = true;
SC_TEST_EXPECT(*taggedMap.get<Compile::enableRTTI>());
}
#define SC_TEST_EXPECT(e)
Records a test expectation (eventually aborting or breaking o n failed test)
Definition: Testing.h:113