Skip to content

Instantly share code, notes, and snippets.

@Ferdi265
Last active July 2, 2020 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ferdi265/6e5d982d6d568f20fa9fc8cfd27906e5 to your computer and use it in GitHub Desktop.
Save Ferdi265/6e5d982d6d568f20fa9fc8cfd27906e5 to your computer and use it in GitHub Desktop.
C++ struct templates in local scope
#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