Created
July 15, 2015 00:11
-
-
Save Fiona-J-W/769923f85d426d42a569 to your computer and use it in GitHub Desktop.
Template-insanity
This file contains hidden or 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 <iostream> | |
#include <type_traits> | |
template<int Value> using integer = std::integral_constant<int, Value>; | |
template<typename T> struct require_integer{}; | |
template<int Value> struct require_integer<integer<Value>>{using type=void;}; | |
#define REQUIRE_INTEGER(Arg) typename=typename require_integer<Arg>::type | |
enum class point_meta_tag{p}; | |
template< | |
typename X, | |
typename Y, | |
point_meta_tag, | |
REQUIRE_INTEGER(X), | |
REQUIRE_INTEGER(Y) | |
> struct point{}; | |
template<typename X, typename Y> using make_point = point<X, Y, point_meta_tag::p>; | |
template< | |
typename X, | |
typename Y, | |
point_meta_tag, | |
typename Payload, | |
REQUIRE_INTEGER(X), | |
REQUIRE_INTEGER(Y) | |
> struct point_with_payload{}; | |
template<typename X, typename Y, typename Payload> using make_point_with_payload = point_with_payload<X, Y, point_meta_tag::p, Payload>; | |
template<typename T> struct require_point{}; | |
template< | |
template<typename, typename, point_meta_tag, typename...>class Base_Type, | |
typename X, | |
typename Y, | |
point_meta_tag Tag, | |
typename... Tail | |
> struct require_point<Base_Type<X, Y, Tag, Tail...>>{using type=void;}; | |
#define REQUIRE_POINT(Arg) typename=typename require_point<Arg>::type | |
template<typename> struct point_x{}; | |
template< | |
template<typename, typename, point_meta_tag, typename...>class Base_Type, | |
typename X, | |
typename Y, | |
point_meta_tag Tag, | |
typename... Tail | |
> struct point_x<Base_Type<X, Y, Tag, Tail...>> { using type = X; }; | |
template<typename> struct point_y{}; | |
template< | |
template<typename, typename, point_meta_tag, typename...>class Base_Type, | |
typename X, | |
typename Y, | |
point_meta_tag Tag, | |
typename... Tail | |
> struct point_y<Base_Type<X, Y, Tag, Tail...>> { using type = Y; }; | |
template<typename T> using point_x_t = typename point_x<T>::type; | |
template<typename T> using point_y_t = typename point_y<T>::type; | |
template<typename T> constexpr T square(T arg){return arg*arg;} | |
template<typename Lhs, typename Rhs, REQUIRE_POINT(Lhs), REQUIRE_POINT(Rhs)> | |
using square_distance = integer<square(point_x_t<Lhs>::value - point_x_t<Rhs>::value)+square(point_y_t<Lhs>::value - point_y_t<Rhs>::value)>; | |
int main() { | |
std::cout << square_distance<make_point<integer<3>, integer<4>>, make_point_with_payload<integer<5>, integer<-2>, int>>::value << '\n'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment