#pragma once // Distributed under the 3-Clause BSD License. See accompanying // file LICENSE or https://github.com/CLIUtils/CLI11 for details. #include #include #include #include namespace CLI { // Type tools // Copied from C++14 #if __cplusplus < 201402L template using enable_if_t = typename std::enable_if::type; #else // If your compiler supports C++14, you can use that definition instead using std::enable_if_t; #endif template struct is_vector { static const bool value = false; }; template struct is_vector> { static bool const value = true; }; template struct is_bool { static const bool value = false; }; template <> struct is_bool { static bool const value = true; }; namespace detail { // Based generally on https://rmf.io/cxx11/almost-static-if /// Simple empty scoped class enum class enabler {}; /// An instance to use in EnableIf constexpr enabler dummy = {}; // Type name print /// Was going to be based on /// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template /// But this is cleaner and works better in this case template ::value && std::is_signed::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { return "INT"; } template ::value && std::is_unsigned::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { return "UINT"; } template ::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { return "FLOAT"; } /// This one should not be used, since vector types print the internal type template ::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { return "VECTOR"; } template ::value && !std::is_integral::value && !is_vector::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { return "TEXT"; } // Lexical cast /// Integers template ::value, detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { try { output = static_cast(std::stoll(input)); return true; } catch(const std::invalid_argument &) { return false; } catch(const std::out_of_range &) { return false; } } /// Floats template ::value, detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { try { output = static_cast(std::stold(input)); return true; } catch(const std::invalid_argument &) { return false; } catch(const std::out_of_range &) { return false; } } /// String and similar template < typename T, enable_if_t::value && !std::is_integral::value, detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { output = input; return true; } } // namespace detail } // namespace CLI