Last active
April 18, 2019 11:16
-
-
Save kim366/8112a8f1603951e81c8d23cff27db135 to your computer and use it in GitHub Desktop.
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 <any> | |
#include <cassert> | |
#include <utility> | |
#include <vector> | |
enum class param_type | |
{ | |
templated, | |
normal | |
}; | |
struct type_name_t | |
{ | |
type_name_t(const char* name) : name(name) {} | |
type_name_t(const char* name, std::vector<type_name_t> parameters) | |
: type(param_type::templated) | |
, name(name) | |
, parameters(std::move(parameters)) | |
{ | |
} | |
param_type type = param_type::normal; | |
const char* name; | |
std::vector<type_name_t> parameters; | |
}; | |
template<typename T> | |
struct types_match_impl | |
{ | |
constexpr static bool synced() { return false; } | |
}; | |
#define IMPL_ASSERT_SYNC \ | |
static_assert(types_match_impl<SyncedT>::synced(), \ | |
"Type not synced (type labelled as SyncedT)!") | |
#define IMPL_COMMON_TYPE_MATCH(type_name) \ | |
static auto type() \ | |
{ \ | |
static auto type = type_name; \ | |
return type; \ | |
} \ | |
\ | |
constexpr static bool synced() { return true; } | |
#define SYNC(cpp_type, type_name) \ | |
template<> \ | |
struct types_match_impl<cpp_type> \ | |
{ \ | |
IMPL_COMMON_TYPE_MATCH(type_name) \ | |
\ | |
static bool match(type_name_t other) \ | |
{ \ | |
return other.type == param_type::normal && other.name == type(); \ | |
} \ | |
} | |
#define SYNC_GENERIC(cpp_template, type_name) \ | |
template<typename... ArgTs> \ | |
struct types_match_impl<cpp_template<ArgTs...>> \ | |
{ \ | |
IMPL_COMMON_TYPE_MATCH(type_name) \ | |
\ | |
static bool match(type_name_t templ_type) \ | |
{ \ | |
return templ_type.type == param_type::templated \ | |
&& sizeof...(ArgTs) == templ_type.parameters.size() \ | |
&& templ_type.name == type() \ | |
&& all_types_match_impl<ArgTs...>::match( \ | |
templ_type.parameters, 0); \ | |
} \ | |
} | |
template<typename...> | |
struct all_types_match_impl; | |
template<typename SyncedT, typename... RestTs> | |
struct all_types_match_impl<SyncedT, RestTs...> | |
{ | |
static bool match(std::vector<type_name_t> types, unsigned n) | |
{ | |
IMPL_ASSERT_SYNC; | |
return types_match_impl<SyncedT>::match(types[n]) | |
&& all_types_match_impl<RestTs...>::match(types, n + 1); | |
} | |
}; | |
template<> | |
struct all_types_match_impl<> | |
{ | |
static bool match(std::vector<type_name_t>, unsigned) { return true; } | |
}; | |
template<typename...> | |
struct sync_force_resolve_impl; | |
template<typename T, typename... Ts> | |
struct sync_force_resolve_impl<T, Ts...> | |
{ | |
static void resolve() | |
{ | |
(void)types_match_impl<T>::type(); | |
sync_force_resolve_impl<Ts...>::resolve(); | |
} | |
}; | |
template<> | |
struct sync_force_resolve_impl<> | |
{ | |
static void resolve() {} | |
}; | |
template<typename... Ts> | |
void sync_force_resolve() | |
{ | |
sync_force_resolve_impl<Ts...>::resolve(); | |
} | |
template<typename SyncedT> | |
bool types_match(type_name_t name) | |
{ | |
IMPL_ASSERT_SYNC; | |
return types_match_impl<SyncedT>::match(name); | |
} | |
////////////////////////////////////////////////// | |
template<typename T, typename U> | |
struct vec | |
{ | |
T x; | |
U y; | |
}; | |
template<typename T> | |
struct single_vec | |
{ | |
T x; | |
}; | |
SYNC(int, "int"); | |
SYNC(bool, "bool"); | |
SYNC(double, "double"); | |
SYNC_GENERIC(vec, "Vec"); | |
SYNC_GENERIC(single_vec, "SingleVec"); | |
const auto int_vec = type_name_t{"Vec", {"int", "int"}}; | |
const auto mixed_vec = type_name_t{"Vec", {"bool", "double"}}; | |
const auto single_vec_i = type_name_t{"Vec", {"int", "bool"}}; | |
const auto nested_vec = type_name_t{"SingleVec", {single_vec_i}}; | |
int main() | |
{ | |
sync_force_resolve<int, double>(); | |
assert(types_match<int>("int")); | |
assert(types_match<double>("double")); | |
assert(!types_match<int>("double")); | |
assert((types_match<vec<int, int>>(int_vec))); | |
assert((types_match<vec<bool, double>>(mixed_vec))); | |
assert((types_match<single_vec<vec<int, bool>>>(nested_vec))); | |
assert(!(types_match<single_vec<vec<int, int>>>(nested_vec))); | |
assert(!(types_match<single_vec<bool>>(nested_vec))); | |
assert((types_match<vec<int, bool>>(single_vec_i))); | |
assert(!(types_match<vec<bool, bool>>(single_vec_i))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment