Created
June 23, 2019 13:24
-
-
Save aliakseis/f24775bfa016b5a7d49b2d0413451ab0 to your computer and use it in GitHub Desktop.
Reflection on C++ 17 variation
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
| // https://gist.github.com/utilForever/1a058050b8af3ef46b58bcfa01d5375d | |
| #include <tuple> | |
| #include <type_traits> | |
| #include <cassert> | |
| #include <iostream> | |
| template <class T, class... TArgs> | |
| decltype(void(T{std::declval<TArgs>()...}), std::true_type{}) test_is_braces_constructible(int); | |
| template <class, class...> std::false_type test_is_braces_constructible(...); | |
| template <class T, class... TArgs> using is_braces_constructible | |
| = decltype(test_is_braces_constructible<std::decay_t<T>, TArgs...>(0)); | |
| struct any_type { | |
| template<class T> | |
| constexpr operator T(); // non explicit | |
| }; | |
| #define PARAMS_MACRO_1(macro) macro(1) | |
| #define PARAMS_MACRO_2(macro) PARAMS_MACRO_1(macro), macro(2) | |
| #define PARAMS_MACRO_3(macro) PARAMS_MACRO_2(macro), macro(3) | |
| #define PARAMS_MACRO_4(macro) PARAMS_MACRO_3(macro), macro(4) | |
| #define PARAMS_MACRO_5(macro) PARAMS_MACRO_4(macro), macro(5) | |
| #define PARAMS_MACRO_6(macro) PARAMS_MACRO_5(macro), macro(6) | |
| #define PARAMS_MACRO_7(macro) PARAMS_MACRO_6(macro), macro(7) | |
| #define PARAMS_MACRO_8(macro) PARAMS_MACRO_7(macro), macro(8) | |
| #define PARAMS_MACRO_9(macro) PARAMS_MACRO_8(macro), macro(9) | |
| #define GENERATE_MULTIPARAMS(macro) \ | |
| macro(PARAMS_MACRO_1) \ | |
| macro(PARAMS_MACRO_2) \ | |
| macro(PARAMS_MACRO_3) \ | |
| macro(PARAMS_MACRO_4) \ | |
| macro(PARAMS_MACRO_5) \ | |
| macro(PARAMS_MACRO_6) \ | |
| macro(PARAMS_MACRO_7) \ | |
| macro(PARAMS_MACRO_8) \ | |
| macro(PARAMS_MACRO_9) | |
| #define TYPE_MACRO(v) any_type | |
| #define ARGS_MACRO(v) p##v | |
| #define TO_TUPLE_MACRO(macro) \ | |
| template<typename T, std::enable_if_t < \ | |
| is_braces_constructible<T, macro(TYPE_MACRO)>::value \ | |
| && !is_braces_constructible<T, macro(TYPE_MACRO), any_type>::value \ | |
| , int> = 0> \ | |
| auto to_tuple(T&& object) noexcept \ | |
| { \ | |
| auto&&[macro(ARGS_MACRO)] = object; \ | |
| return std::make_tuple(macro(ARGS_MACRO)); \ | |
| } | |
| GENERATE_MULTIPARAMS(TO_TUPLE_MACRO) | |
| int main() { | |
| { | |
| struct s { | |
| int p1; | |
| double p2; | |
| }; | |
| auto t = to_tuple(s{1, 2.0}); | |
| static_assert(std::is_same<std::tuple<int, double>, decltype(t)>{}); | |
| assert(1 == std::get<0>(t)); | |
| assert(2.0 == std::get<1>(t)); | |
| } | |
| { | |
| struct s { | |
| struct nested { } p1; | |
| int p2; | |
| int p3; | |
| s* p4; | |
| }; | |
| auto t = to_tuple(s{s::nested{}, 42, 87, nullptr}); | |
| static_assert(std::is_same<std::tuple<s::nested, int, int, s*>, decltype(t)>{}); | |
| assert(42 == std::get<1>(t)); | |
| assert(87 == std::get<2>(t)); | |
| assert(nullptr == std::get<3>(t)); | |
| } | |
| std::cout << "ok.\n"; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment