A semanic typedef is a kind of "strong typedef" that prevents implicit
conversion between itself and its underlying type. But rather than a
straight typedef of the base type with all operators available, a
semantic typedef allows the new type to choose the operators available
to it, increasing type safety.
An example:
// It doesn't make sense to add two CacheLineSize objects together, so
// don't define add-assignment.
struct CacheLineSize : public SemanticTypedef<CacheLineSize, unsigned>,
: public EqualityCompare<CacheLineSize>,
: public LessThanCompare<CacheLineSize> {
using SemanticTypedef::SemanticTypedef;
};
CacheLineSize ASize(32);
CacheLineSize BSize(64);
assert(ASize < BSize);
static_assert(!std::is_convertible<decltype(ASize),
UnderlyingType<decltype(ASize)>>::value,
"Converted CacheLineSize to its underlying type!");
static_assert(!std::is_convertible<UnderlyingType<decltype(ASize)>,
decltype(ASize)>::value,
"Converted underlying type to CacheLineSize!");This commit defines the basic SemanticTypedef class along with classes
to make the most common operators available: ==, <, >=, =, +=, &&, ||,
!, << (output streaming).
I know this has been discussed on the thread, but I feel obligated to point out that there is already precedent for using the term "strong typedef" for this kind of thing: LLVM_YAML_STRONG_TYPEDEF. Might not matter if the goal is to eventually replace LLVM_YAML_STRONG_TYPEDEF with this, but otherwise, it would be nice to maintain consistent naming within the project.