Skip to content

Instantly share code, notes, and snippets.

@AlexCeleste
Created February 14, 2023 13:36
Show Gist options
  • Save AlexCeleste/170195deae827f02a95aa03abc5f5c3b to your computer and use it in GitHub Desktop.
Save AlexCeleste/170195deae827f02a95aa03abc5f5c3b to your computer and use it in GitHub Desktop.
partial specialization in C
#define IsArray(V) _Generic((0, V) \
, typeof(V): false \
, default: true)
char ca[] = "hello";
int ia[10] = {};
static_assert (IsArray(ca));
static_assert (IsArray(ia));
char const * cp = ca;
char const * ip = ia;
static_assert (!IsArray (cp));
static_assert (!IsArray (ip));
#define DeclVal(V) (&(typeof(V)){0})
#define LValType(T) typeof(T) *
#define static_if(P, T, E) \
_Generic(&(int[!!(P) + 1]){0} \
, LValType (int[2]) : (T) \
, LValType (int[1]) : (E)) \
#define CountOf(A) (IsArray(A) \
? sizeof(A) / sizeof(static_if (IsArray(A), (A), &(char){0})[0]) \
: 1)
#define MatchArray(V) _Generic(DeclVal(V) \
, LValType (int [CountOf(V)]) : true \
, LValType (char[CountOf(V)]) : true \
, default : false)
int i;
char c;
static_assert (MatchArray (ca));
static_assert (MatchArray (ia));
static_assert (!MatchArray (cp));
static_assert (!MatchArray (ip));
static_assert (!MatchArray (c));
static_assert (!MatchArray (i));
#include <limits.h>
_BitInt(4) x4;
_BitInt(8) x8;
_BitInt(32) x32;
_BitInt(57) x57;
_BitInt(64) x64;
_BitInt(75) x75;
_BitInt(127) x127;
_BitInt(128) x128;
_BitInt(129) x129;
_BitInt(200) x200;
_BitInt(201) x201;
_BitInt(202) x202;
static_assert (sizeof (x200) == sizeof (x202));
static_assert (sizeof (x201) == sizeof (x202));
#define PrecLeq(V, P) _Generic ((V) + (unsigned _BitInt(P))0 \
, unsigned _BitInt(P): true, default: false)
static_assert (PrecLeq (x200, 200));
static_assert (PrecLeq (x200, 202));
static_assert (!PrecLeq (x202, 200));
#define FindPrec1(V, Ofs) (PrecLeq(V, Ofs + 0) ? Ofs + 0 : Ofs + 1)
#define FindPrec2(V, Ofs) (PrecLeq(V, Ofs + 1) ? FindPrec1(V, Ofs) : FindPrec1 (V, Ofs + 2))
#define FindPrec3(V, Ofs) (PrecLeq(V, Ofs + 3) ? FindPrec2(V, Ofs) : FindPrec2 (V, Ofs + 4))
#define FindPrec4(V, Ofs) (PrecLeq(V, Ofs + 7) ? FindPrec3(V, Ofs) : FindPrec3 (V, Ofs + 8))
#define FindPrec5(V, Ofs) (PrecLeq(V, Ofs + 15) ? FindPrec4(V, Ofs) : FindPrec4 (V, Ofs + 16))
#define FindPrec6(V, Ofs) (PrecLeq(V, Ofs + 31) ? FindPrec5(V, Ofs) : FindPrec5 (V, Ofs + 32))
#define FindPrec7(V, Ofs) (PrecLeq(V, Ofs + 63) ? FindPrec6(V, Ofs) : FindPrec6 (V, Ofs + 64))
#define FindPrecOfs(V, VB) FindPrec7(V, (VB > 128 ? VB - 127 : 1))
#define FindPrec(V) FindPrecOfs((V), (sizeof(V)*CHAR_BIT))
static_assert (FindPrec(x57) == 57);
static_assert (FindPrec(x64) == 64);
static_assert (FindPrec(x75) == 75);
static_assert (FindPrec(x127) == 127);
static_assert (FindPrec(x128) == 128);
static_assert (FindPrec(x129) == 129);
static_assert (FindPrec(x200) == 200);
static_assert (FindPrec(x202) == 202);
#define IsBitPrecise(V) _Generic ((V) \
, signed _BitInt( FindPrec(V) ): true \
, unsigned _BitInt( FindPrec(V) ): true \
, default: false)
int xi;
short xs;
long xl;
static_assert (!IsBitPrecise (xi));
static_assert (!IsBitPrecise (xi));
static_assert (!IsBitPrecise (xi));
static_assert (IsBitPrecise (x32));
static_assert (IsBitPrecise (x57));
static_assert (IsBitPrecise (x129));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment