// Copyright (C) 2022 johannst #include template class Checker, typename = void> struct is_valid : std::false_type {}; template class Checker> struct is_valid>> : std::true_type {}; template class Checker> static constexpr bool is_valid_v = is_valid::value; // ----------------------------------------------------------------------------- template class Checker, typename = void> struct is_valid_with_ret : std::false_type {}; template class Checker> struct is_valid_with_ret>> : std::is_same> {}; template class Checker> static constexpr bool is_valid_with_ret_v = is_valid_with_ret::value; // ----------------------------------------------------------------------------- template struct is_entry { template using init = decltype(std::declval().init()); template using tag = decltype(std::declval().tag()); template using val = decltype(std::declval().val()); static constexpr bool value = is_valid_v && is_valid_with_ret_v && is_valid_with_ret_v; }; template static constexpr bool is_entry_v = is_entry::value; template struct Entry { using Type = E; void init(); int tag() const; E val() const; }; int main() { static_assert(is_entry_v>, ""); }