How to implement custom traits (C++11)
#include <type_traits>
#include <iostream>
using std::enable_if;
using std::is_same;
using std::declval;
using std::integral_constant;
template <typename T>
using Invoke = typename T::type;
template <typename If, typename Then, typename Else>
using Conditional = Invoke<std::conditional<If::value, Then, Else>>;
template <typename... T>
struct All : std::true_type {};
template <typename Head, typename... Tail>
struct All<Head, Tail...> : Conditional<Head, All<Tail...>, std::false_type> {};
template <typename... Condition>
using EnableIf = typename std::enable_if<All<Condition...>::value>;
#define GPC_EXTEND_BOOL_TRAIT(name, ...) template <typename T> struct name<EnableIf<__VA_ARGS__>> : std::true_type {};
#define GPC_DEFINE_BOOL_TRAIT(name, ...) template <typename T> struct name: std::false_type {}; GPC_EXTEND_BOOL_TRAIT(name, __VA_ARGS__)
//--------------------------------------
// ok
//template <typename T>
//struct has_2d_coordinates: std::false_type {};
// ok
//template <typename T>
//struct has_2d_coordinates<std::enable_if<is_same<decltype(declval<T>().x), int>::value && is_same<decltype(declval<T>().y), int>::value>>: std::true_type {};
// ok
//template <typename T>
//struct has_2d_coordinates<std::enable_if<All<is_same<decltype(declval<T>().x), int>, is_same<decltype(declval<T>().y), int> >::value > >: std::true_type {};
// ok
//template <typename T> struct has_2d_coordinates< EnableIf< is_same<decltype(declval<T>().x), int>, is_same<decltype(declval<T>().y), int> >>: std::true_type {};
GPC_DEFINE_BOOL_TRAIT(has_2d_coordinates, is_same<decltype(declval<T>().x), int>, is_same<decltype(declval<T>().y), int>)
GPC_EXTEND_BOOL_TRAIT(has_2d_coordinates, is_same<decltype(declval<T>().x()), int>, is_same<decltype(declval<T>().y()), int>)
template <typename T>
void report(const char *name) {
std::cout << name << " " << (has_2d_coordinates<T>::value ? "HAS 2D COORDINATES" : "DOESN'T have 2D coordinates") << std::endl;
}
#define REPORT(T) report<T>(#T)
int main() {
struct EmptyStruct {};
REPORT(EmptyStruct);
struct Point { int x, y; };
REPORT(Point);
struct BadPoint { int x_, y; };
REPORT(BadPoint);
struct BadPoint2 { int x, y_; };
REPORT(BadPoint2);
struct BadPoint3 { double x, y; };
REPORT(BadPoint3);
}