Last active
July 2, 2020 21:33
-
-
Save Ferdi265/6e5d982d6d568f20fa9fc8cfd27906e5 to your computer and use it in GitHub Desktop.
C++ struct templates in local scope
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
#define DEFINE_LOCAL_VALUE_TEMPLATE(name, value) \ | |
[](auto __t){ \ | |
using name = std::remove_reference_t<decltype(__t)>; \ | |
return value; \ | |
} | |
#define DEFINE_LOCAL_TYPE_TEMPLATE(name, ...) \ | |
[](auto __t){ \ | |
using name = std::remove_reference_t<decltype(__t)>; \ | |
__VA_ARGS__ *__s = nullptr; \ | |
return *__s; \ | |
} | |
#define CALL_LOCAL_VALUE_TEMPLATE(name, arg_type) \ | |
name(std::declval<arg_type>()) | |
#define CALL_LOCAL_TYPE_TEMPLATE(name, arg_type) \ | |
decltype(CALL_LOCAL_VALUE_TEMPLATE(name, arg_type)) | |
void wat() { | |
struct nil {}; | |
auto prepend = DEFINE_LOCAL_VALUE_TEMPLATE(Head, | |
DEFINE_LOCAL_TYPE_TEMPLATE(Tail, | |
struct { | |
using type = Head; | |
using next = Tail; | |
} | |
) | |
); | |
using list_of_integral_types = | |
CALL_LOCAL_TYPE_TEMPLATE(CALL_LOCAL_VALUE_TEMPLATE(prepend, char), | |
CALL_LOCAL_TYPE_TEMPLATE(CALL_LOCAL_VALUE_TEMPLATE(prepend, short), | |
CALL_LOCAL_TYPE_TEMPLATE(CALL_LOCAL_VALUE_TEMPLATE(prepend, int), | |
CALL_LOCAL_TYPE_TEMPLATE(CALL_LOCAL_VALUE_TEMPLATE(prepend, long), | |
CALL_LOCAL_TYPE_TEMPLATE(CALL_LOCAL_VALUE_TEMPLATE(prepend, long long), | |
nil))))); | |
auto silly_pair = DEFINE_LOCAL_TYPE_TEMPLATE(T, | |
struct { | |
T _1; | |
T _2; | |
} | |
); | |
using int_pair = | |
CALL_LOCAL_TYPE_TEMPLATE(silly_pair, list_of_integral_types::next::next::type); | |
constexpr int_pair p{ | |
42, | |
1337 | |
}; | |
static_assert(p._1 + p._2 == 1379); | |
} | |
int main() { | |
wat(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment