known(T, expr) — Cheap Compile-Time Type Assertion

known(T, expr) asserts at compile time that expr is of type T, then passes the value through unchanged. It is a zero-cost alternative to inline functions for type-checking inside macros.

int* ptr = get_ptr();
void* p = known(int*, ptr);    // OK: ptr is int*

char* wrong = get_char();
void* p = known(int*, wrong);  // ERROR (C++ build): type mismatch

In C, known(T, expr) is (expr) — a no-op. The C++ build uses a static_assert that fires if the types don’t match.

Why Not an Inline Function?

Three reasons:

  1. Debug build cost. Inline functions are not inlined in debug builds. known() is zero cost even in -O0.
  2. Const propagation. A function must pick const T* or T*. known() passes through whatever constness the expression has (lenient) or errors on mismatch (rigid).
  3. Macro composability. Writing a macro that delegates to a function for type checking forces split definitions. known() stays inside the macro.

Lenient vs. Rigid

Variant Behavior
lenient_known(T, expr) Accepts const T when T is specified; passes const through
rigid_known(T, expr) Errors if expr has different const-ness than T
known(T, expr) Alias for lenient_known
const int* cp = get_const();
int* mp = get_mutable();

lenient_known(int*, cp);   // OK: accepts const int* when int* specified
rigid_known(int*, cp);     // ERROR: cp is const int*, not int*
rigid_known(int*, mp);     // OK: exact match

known_not and known_any

known_not(int*, expr)               // asserts expr is NOT int*
known_any((int*, char*, void*), expr)  // asserts expr is one of the listed types

lenient_exactly and rigid_exactly

These check that expr is exactly a specified type (no inheritance or implicit conversions). lenient_exactly(T, expr) accepts const T as a match; rigid_exactly(T, expr) requires the exact type including mutability.

known_lvalue

known_lvalue(variable)   // compile error if variable is not an lvalue

Useful in “evil macros” that use their arguments more than once: ensures the caller passes a simple variable, not an expression with side effects.


Compile-Time Tests

Basic type assertion

#define NEEDFUL_CPP_ENHANCED  1
#include <cassert>
#include "needful.h"

int main() {
    int value = 10;
    int* ptr = &value;

    void* p = lenient_known(int*, ptr);  // OK: ptr is int*
    (void)p;

    const int* cp = ptr;
    const void* q = lenient_known(int*, cp);   // OK: lenient accepts const int*, passes through as const int*
    (void)q;

    return 0;
}

rigid_known rejects a const pointer where mutable is required

// MATCH-ERROR-TEXT: static assertion failed  <- GCC/Clang
// MATCH-ERROR-TEXT: static_assert            <- MSVC
#define NEEDFUL_CPP_ENHANCED  1
#include <cassert>
#include "needful.h"

int main() {
    const int* cp = nullptr;
    int* p = rigid_known(int*, cp);  // ERROR: const int* != int*
    (void)p;
    return 0;
}