Skip to content

Instantly share code, notes, and snippets.

@Fiona-J-W
Created July 15, 2015 00:11
Show Gist options
  • Save Fiona-J-W/769923f85d426d42a569 to your computer and use it in GitHub Desktop.
Save Fiona-J-W/769923f85d426d42a569 to your computer and use it in GitHub Desktop.
Template-insanity
#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