Skip to content

Instantly share code, notes, and snippets.

  • Save fish2000/0ca4a834feb4d2e817c9 to your computer and use it in GitHub Desktop.
Save fish2000/0ca4a834feb4d2e817c9 to your computer and use it in GitHub Desktop.
These Dirty, Filthy Casting Function Templates Know Exactly What You Need
/// Originally from the Geordi project, mirrored here:
/// https://github.com/Eelis/geordi/blob/master/prelude/evil_casts.hpp
///
/// Written by the Geordi authors - q.v. http://www.eelis.net/geordi/
/// Reformatted and annotated by Alexander Bohn - q.v. https://about.me/alexanderbohn
#ifndef EVIL_CASTS_HPP
#define EVIL_CASTS_HPP
//
// Consider:
//
// some_evil_cast_operation<char const *>("foo")
//
// … There are two possible interpretations for the result: either
// a) the array should decay into a pointer and be immediately returned, or
// b) the bytes making up the array are interpreted
// as the bytes making up the to-be-returned pointer.
//
// … `cast_dammit_cast<T>()` does the former, while `savage_cast<T>()` does the latter.
//
template <typename To, typename From>
To savage_cast (From const & from) {
//
// `savage_cast<ToType>()` can even be used†̂‡ to check endianness:
//
// geordi << hex << savage_cast<uint32_t>("\xef\xbe\xad\xde"))
//
// ‡. Specifically, “used” as in “used as an operand to something std::ostream-ish,”
// I believe. -ed
//
return (To const &) from;
}
template <typename To, typename From>
To cast_dammit_cast (From const from) {
//
// Note that the argument (of type `From` here) is itself is passed
// to `cast_damnit_cast<To, From>() by *value* -- we want to ensure
// our array operands will decay to pointer types.
From const & r = from;
//
// Amongst other things, the “old one-two” of pass-by-value,
// then-assign-to-lvalue constrains the cast operations’ return type,
// such that `cast_dammit_cast<char*>("oi")` will work as one would expect‡.
//
return (To const &) r;
//
// ‡. I confess I don’t know what that would be in this case -- the `damnit`
// operator variant is supposed to be the pointer-decayer and NOT the
// address-reassignment-byte-value-reinterpreter, or whatever; I can’t
// really guess at what the expression `cast_dammit_cast<char*>("oi")`
// *SHOULD* do in, like the first place; far be it then from be to even begin
// to speculate on what side-effects or glitchy corner-cases there may be (like,
// specifically where the semantics and syntax are somehow clashing) -- at least,
// not beyond some kind of biased armchair-psychology guess, at best, at the
// intent of the author (whom I should point out is way talented and awesome
// and generally smart; this is not about him).
//
// And so yeah: now that I have thoroughly overthought this whole thing,
// my only feeling about how casting a constexpr string to a char pointer
// could, somehow maybe, be a weird situation -- even when the demand for
// said cast is heartily puncuated with alliterative and profane emphases --
// is that OK, does it cast away cv-qualifiers? That “cv” stands of course
// for “const-volatile;” if you feel like introducing some nondeterministically
// and not-easily-reproduced storage-durability bugs, well then son you'll
// hurt yourself with `const_cast<>()` just like your father did, and just like
// his father did before that. So ah yeah but beyond that really I don’t know, erm.
// Meanwhile I’ll trust the author’s brainyness in this case, and look forward
// to whatever ever-more-expressively abusive type-system shortcuts that my peers
// in the C++ industry manage wring out of their mismanaged anger, yes.
//
}
#endif // header guard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment