diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index ff17ec4..fe7d8ef 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -448,14 +448,14 @@ namespace cxxopts { if (negative) { - if (u > U(-std::numeric_limits::min())) + if (u > static_cast(-std::numeric_limits::min())) { throw argument_incorrect_type(text); } } else { - if (u > std::numeric_limits::max()) + if (u > static_cast(std::numeric_limits::max())) { throw argument_incorrect_type(text); } @@ -479,6 +479,23 @@ namespace cxxopts } } + template + R + checked_negate(T&& t, const std::string&, std::true_type) + { + // if we got to here, then `t` is a positive number that fits into + // `R`. So to avoid MSVC C4146, we first cast it to `R`. + // See https://github.com/jarro2783/cxxopts/issues/62 for more details. + return -static_cast(t); + } + + template + T + checked_negate(T&&, const std::string& text, std::false_type) + { + throw argument_incorrect_type(text); + } + template void integer_parser(const std::string& text, T& value) @@ -537,11 +554,14 @@ namespace cxxopts if (negative) { - if (!is_signed) - { - throw argument_incorrect_type(text); - } - value = -result; + value = checked_negate(result, + text, + std::integral_constant()); + //if (!is_signed) + //{ + // throw argument_incorrect_type(text); + //} + //value = -result; } else {