An experimental C++ strong typedef-ish thingie
Highly experimental, for now.
Public domain. May change to something else if experimentation proves successful.
Very much inspired by @foonathan's
type_safe library, but aim is
slightly different. Limit scope for type safety only. No runtime checks. Also
strive for a higher level abstraction of the needed functionality. The idea
is to suffer no runtime penalty, but to capture misuse at compile time
(for example accidentally subtracting from a handle, or swapping two parameters
in a function call) while still being easy to use for inexperienced
#include <strong_type.hpp> using myint = strong::type<int, struct my_int_>;
myint is a very basic handle. You can initialize it. You can do
equal/not-equal comparison with other instances of the same type, and you can
access its underlying
int instance with
To get the underlying type of a strong type, use
typename strong::underlying_type<mytype>::type, or the convenience alias
mytype is not a
using otherint = strong::type<int, struct other_int_>;
otherint is a distinct type from
myint. If a function takes an argument of
myint, you can't pass it an instance of
otherint, and vice-versa. You
also can't cross-assign, cross-create or cross-compare.
To access more functionality, you add modifiers. For example:
using ordered_int = strong::type<int, ordered_int_, strong::ordered>;
ordered_int now supports relational order comparisons, like
(provided the underlying type, int this case
int, does.) Type
can thus be used as key in
Other modifiers are:
strong::iostreamable, which provide the default iostream integrations (as handled by the underlying type.) Provide your own operators instead if you prefer that.
operator--. bicrementable is obviously a made- up word for the occasion, but I think its meaning is clear.
explicit operator bool() const, providing the underlying type supports it.
std::hash<>on the type (forwards to the underlying type,) to allow use in
strong::differenceallows instances to be subtracted and added (yielding a
strong::difference,) divideded (yielding the base type), or multiplied or divided with the base type, yielding another
strong::affine_point<D>allows instances to be subtracted (yielding a
D) or to add or subtract a
Dto an instance. See Affine Space. Examples of one dimentional affine points are pointer (with
D.) An example of a multidimensional affine point is a coordinate (with a vector type for
D.) It is natural that
Dis of a
strong::differencetype. This is a good name from a mathematical point of view, but perhaps a bit too academic, and not well aligned with the other names.
operator->, and comparisons with
nullptrproviding the underlying type supports it.
strong::arithmeticallows addition, subtraction, multiplication, division and remainder of instances.
^and shift operations.
strong::indexed<D>allows use of the subscript operator on type
D. This also allows member function
at(D), providing the underlying type supports it. A lame version
indexed<>allows subscript on any type that works.
strong::iteratoradds functionality needed depending on iterator category. If the iterator type is a
random_access_iterator, the strong type is
strong::affine_point<difference_type>. It should be possible to specify the index type and affine_point type.
strong::rangeadds the functionality needed to iterate over the elements. the iterator types are using the same tag as using in the range. Only implements types
const_iterator, and thus
.end() const. Are reverse iterators important, and thus
strong::arithmetic, the type trait
std::is_arithmetic<> is true.
strong::iterator, the type trait
the traits of the underlying iterator type.
Which are the right modifiers to have? Going into too fine detail makes no
sense and becomes a burden.
iterator? One for each iterator category?
To build the self-test program:
cmake <strong_type_dir> -DCMAKE_BUILD_TYPE=Debug cmake --build . --target self_test
N.B. It looks like Microsoft Visual Studio MSVC compiler really doesn't like this code. If you're familier with MSVC idiosyncracies and/or willing to file bug reports, please lend a hand.
Discussions, pull-requests, flames are welcome.