Skip to content

Instantly share code, notes, and snippets.

@ikskuh
Created April 26, 2019 14:13
Show Gist options
  • Save ikskuh/2525138929ae1d137fe4dd37be5bf4ed to your computer and use it in GitHub Desktop.
Save ikskuh/2525138929ae1d137fe4dd37be5bf4ed to your computer and use it in GitHub Desktop.
Tagged, configurable integer type which allows only "self-interaction"
#include <type_traits>
template<
typename Tag, // Discriminator
typename UnderlyingType = std::size_t, // What integer are we defining
bool EnableOrdering = true, // Allow relational operators
bool EnableBitwise = false, // Allow bitwise operators
bool EnableArithmetic = false // Allow arithmetic operators
>
struct tagged_int
{
static_assert(std::is_integral_v<UnderlyingType>);
UnderlyingType value;
constexpr tagged_int() : value(0) { }
constexpr tagged_int(UnderlyingType val) : value(val) { }
};
#define DEFINE_TAGGED_INT_OPERATOR(_Oper, _Cond, _Msg) \
template<typename T, typename U, bool O, bool B, bool A> \
constexpr auto operator _Oper (tagged_int<T,U,O,B,A> lhs, tagged_int<T,U,O,B,A> rhs) \
{ \
static_assert(_Cond, _Msg); \
return lhs.value _Oper rhs.value; \
}
#define DEFINE_TAGGED_INT_SETTER(_Oper, _Cond, _Msg) \
template<typename T, typename U, bool O, bool B, bool A> \
constexpr tagged_int<T,U,O,B,A> & operator _Oper (tagged_int<T,U,O,B,A> & lhs, tagged_int<T,U,O,B,A> rhs) \
{ \
static_assert(_Cond, _Msg); \
lhs.value _Oper rhs.value; \
return lhs; \
}
DEFINE_TAGGED_INT_OPERATOR(==, true, "")
DEFINE_TAGGED_INT_OPERATOR(!=, true, "")
DEFINE_TAGGED_INT_OPERATOR(>, O, "tagged_int has no ordering enabled!")
DEFINE_TAGGED_INT_OPERATOR(<, O, "tagged_int has no ordering enabled!")
DEFINE_TAGGED_INT_OPERATOR(>=, O, "tagged_int has no ordering enabled!")
DEFINE_TAGGED_INT_OPERATOR(<=, O, "tagged_int has no ordering enabled!")
DEFINE_TAGGED_INT_OPERATOR(&, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(|, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(^, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_SETTER(|=, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_SETTER(&=, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_SETTER(^=, B, "tagged_int has no bitwise operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(+, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(-, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(*, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(/, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_OPERATOR(%, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_SETTER(+=, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_SETTER(-=, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_SETTER(*=, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_SETTER(/=, A, "tagged_int has no arithmetic operations enabled!")
DEFINE_TAGGED_INT_SETTER(%=, A, "tagged_int has no arithmetic operations enabled!")
#undef DEFINE_TAGGED_INT_OPERATOR
#undef DEFINE_TAGGED_INT_SETTER
#include "tagged_int.h"
using myint = tagged_int<struct myint_tag, int, true, true, true>;
using myid = tagged_int<struct myid_tag, std::size_t, true, false, false>;
constexpr void test_myint()
{
myint a, b;
a = myint { 10 };
a = b;
a == b;
a != b;
a > b;
a < b;
a >= b;
a <= b;
a | b;
a & b;
a ^ b;
a |= b;
a &= b;
a ^= b;
a + b;
a - b;
a * b;
a / b;
a % b;
a += b;
a -= b;
a *= b;
a /= b;
a %= b;
}
constexpr void test_myid()
{
myid a, b;
a = myid { 10 };
a = b;
a == b;
a != b;
a > b;
a < b;
a >= b;
a <= b;
/* everything from here throws errors
a | b;
a & b;
a ^ b;
a + b;
a - b;
a * b;
a / b;
a % b;
// */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment