-
-
Save blockspacer/39c78c0799317b987ef0467bff97dcb0 to your computer and use it in GitHub Desktop.
How to implement custom #traits (C++11)
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 <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); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment