#include #include #include template struct conversion_chain; template struct conversion_chain { static bool const step { std::is_convertible_v }; using next = std::conditional_t< step, First, T >; using chain = conversion_chain; static std::size_t const length { step + chain::length }; }; template struct conversion_chain { static std::size_t const length { 0 }; }; template struct longest_conversion_chain; template struct longest_conversion_chain { static std::size_t const current { conversion_chain::length + 1 }; static std::size_t const next { longest_conversion_chain::length }; static std::size_t const length { std::max(current, next) }; }; template <> struct longest_conversion_chain<> { static std::size_t const length { 0 }; }; int main() { // empty chain static_assert( longest_conversion_chain<>::length == 0 ); // single type static_assert( longest_conversion_chain::length == 1 ); // same type twice static_assert( longest_conversion_chain::length == 2 ); // all types is a chain static_assert( longest_conversion_chain::length == 2 ); static_assert( longest_conversion_chain::length == 3 ); // two incompatible chains (int and string) static_assert( longest_conversion_chain::length == 1 ); // can it find the char const* -> std::string chain? static_assert( longest_conversion_chain::length == 2 ); static_assert( longest_conversion_chain::length == 2 ); static_assert( longest_conversion_chain::length == 2 ); // can it find the int -> float -> double chain? static_assert( longest_conversion_chain::length == 3 ); static_assert( longest_conversion_chain::length == 3 ); // three chains of equal length static_assert( longest_conversion_chain::length == 2 ); // three chains (int, string -> string, int* -> int* -> int*) static_assert( longest_conversion_chain::length == 3 ); }