Skip to content

Instantly share code, notes, and snippets.

@StarrFox
Last active February 4, 2024 01:14
Show Gist options
  • Save StarrFox/be21a873f04c6ac845961b64c7cbb672 to your computer and use it in GitHub Desktop.
Save StarrFox/be21a873f04c6ac845961b64c7cbb672 to your computer and use it in GitHub Desktop.
the Pointer problem
type
Obj = object
objField: int
Property = object
propField: float
RawType[T] = object
Pointer[T, Z] = object
when T is RawType[Z]:
discard
else:
data: T
proc initPointer[T: Obj | Property](x: T): Pointer[T, T] =
Pointer[T, T](data : x)
proc initPointer[T: typedesc[Obj]](x: T): Pointer[RawType[T], T] =
Pointer[RawType[T], T]()
proc get[T, Z](self: Pointer[T, Z]): Z =
when T is RawType[Z]:
Z()
else:
self.data
let a = initPointer(Obj())
let b = initPointer(Property())
let c = initPointer(Obj)
#let d = initPointer(Property) # error
let x = a.get()
let y = b.get()
let z = c.get()
echo x
echo y
echo z
type
Obj = object
objField: int
Property = object
propField: float
RawType[T] = object
Pointer[T: Obj | Property | RawType] = object
when T isnot Obj and T isnot Property:
discard
else:
data: T
proc initPointer[T: Obj | Property](x: T): Pointer[T] =
Pointer[T](data : x)
proc initPointer[T: typedesc[Obj]](x: T): Pointer[RawType[T]] =
Pointer[RawType[T]]()
proc get[T](self: Pointer[T]): T =
self.data
proc get[T](self: Pointer[RawType[T]]): T =
T()
let a = initPointer(Obj())
let b = initPointer(Property())
let c = initPointer(Obj)
#let d = initPointer(Property)
echo a
echo b
echo c
let x = a.get()
let y = b.get()
let z = c.get()
echo x
echo y
echo z
#include <type_traits>
struct Property {};
struct Obj {};
struct TypeOrValueHelper {
// when type: `-h` evaluates to `h`...
consteval TypeOrValueHelper operator-() { return *this; }
// ...then the (TYPE_OR_VALUE) cast invokes this operator on it to produce `T`.
template <typename T>
constexpr operator T() {
if constexpr (!std::is_same_v<T, Property>) {
return T{};
} else {
static_assert(!std::is_same_v<T, T>, "muh property");
}
}
};
// when value: simply returned again as-is here
consteval auto operator-(auto v, TypeOrValueHelper) { return v; }
template <auto Lambda>
struct Pointer {
decltype(auto) get() {
return Lambda();
}
};
#define PointerType(TYPE_OR_VALUE) Pointer<[] { TypeOrValueHelper h; auto v = (TYPE_OR_VALUE)-h; return v; }>
int main() {
PointerType(Obj) p0;
p0.get();
PointerType(Obj{}) p1;
// PointerType(Property) p2; // compile error
PointerType(Property{}) p3;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment