Commit 34784b01f7bdb989e56f268b632091a8a8738906
Committed by
jarro2783
1 parent
fce82fb0
Fix: Make CXXOPTS_NO_EXCEPTIONS compilable and print messages (#196)
Fix CXXOPTS_NO_EXCEPTIONS so that it doesn't warn about unused parameters, and print out error messages.
Showing
1 changed file
with
63 additions
and
126 deletions
include/cxxopts.hpp
| @@ -467,6 +467,26 @@ namespace cxxopts | @@ -467,6 +467,26 @@ namespace cxxopts | ||
| 467 | } | 467 | } |
| 468 | }; | 468 | }; |
| 469 | 469 | ||
| 470 | + template <typename T> | ||
| 471 | + void throw_or_mimic(const std::string& text) | ||
| 472 | + { | ||
| 473 | + static_assert(std::is_base_of<std::exception, T>::value, | ||
| 474 | + "throw_or_mimic only works on std::exception and " | ||
| 475 | + "deriving classes"); | ||
| 476 | + | ||
| 477 | +#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 478 | + // If CXXOPTS_NO_EXCEPTIONS is not defined, just throw | ||
| 479 | + throw T{text}; | ||
| 480 | +#else | ||
| 481 | + // Otherwise manually instantiate the exception, print what() to stderr, | ||
| 482 | + // and abort | ||
| 483 | + T exception{text}; | ||
| 484 | + std::cerr << exception.what() << std::endl; | ||
| 485 | + std::cerr << "Aborting (exceptions disabled)..." << std::endl; | ||
| 486 | + std::abort(); | ||
| 487 | +#endif | ||
| 488 | + } | ||
| 489 | + | ||
| 470 | namespace values | 490 | namespace values |
| 471 | { | 491 | { |
| 472 | namespace | 492 | namespace |
| @@ -495,22 +515,14 @@ namespace cxxopts | @@ -495,22 +515,14 @@ namespace cxxopts | ||
| 495 | { | 515 | { |
| 496 | if (u > static_cast<U>((std::numeric_limits<T>::min)())) | 516 | if (u > static_cast<U>((std::numeric_limits<T>::min)())) |
| 497 | { | 517 | { |
| 498 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 499 | - throw argument_incorrect_type(text); | ||
| 500 | -#else | ||
| 501 | - std::abort(); | ||
| 502 | -#endif | 518 | + throw_or_mimic<argument_incorrect_type>(text); |
| 503 | } | 519 | } |
| 504 | } | 520 | } |
| 505 | else | 521 | else |
| 506 | { | 522 | { |
| 507 | if (u > static_cast<U>((std::numeric_limits<T>::max)())) | 523 | if (u > static_cast<U>((std::numeric_limits<T>::max)())) |
| 508 | { | 524 | { |
| 509 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 510 | - throw argument_incorrect_type(text); | ||
| 511 | -#else | ||
| 512 | - std::abort(); | ||
| 513 | -#endif | 525 | + throw_or_mimic<argument_incorrect_type>(text); |
| 514 | } | 526 | } |
| 515 | } | 527 | } |
| 516 | } | 528 | } |
| @@ -544,13 +556,10 @@ namespace cxxopts | @@ -544,13 +556,10 @@ namespace cxxopts | ||
| 544 | 556 | ||
| 545 | template <typename R, typename T> | 557 | template <typename R, typename T> |
| 546 | T | 558 | T |
| 547 | - checked_negate(T&&, const std::string& text, std::false_type) | 559 | + checked_negate(T&& t, const std::string& text, std::false_type) |
| 548 | { | 560 | { |
| 549 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 550 | - throw argument_incorrect_type(text); | ||
| 551 | -#else | ||
| 552 | - std::abort(); | ||
| 553 | -#endif | 561 | + throw_or_mimic<argument_incorrect_type>(text); |
| 562 | + return t; | ||
| 554 | } | 563 | } |
| 555 | 564 | ||
| 556 | template <typename T> | 565 | template <typename T> |
| @@ -562,11 +571,7 @@ namespace cxxopts | @@ -562,11 +571,7 @@ namespace cxxopts | ||
| 562 | 571 | ||
| 563 | if (match.length() == 0) | 572 | if (match.length() == 0) |
| 564 | { | 573 | { |
| 565 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 566 | - throw argument_incorrect_type(text); | ||
| 567 | -#else | ||
| 568 | - std::abort(); | ||
| 569 | -#endif | 574 | + throw_or_mimic<argument_incorrect_type>(text); |
| 570 | } | 575 | } |
| 571 | 576 | ||
| 572 | if (match.length(4) > 0) | 577 | if (match.length(4) > 0) |
| @@ -603,21 +608,13 @@ namespace cxxopts | @@ -603,21 +608,13 @@ namespace cxxopts | ||
| 603 | } | 608 | } |
| 604 | else | 609 | else |
| 605 | { | 610 | { |
| 606 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 607 | - throw argument_incorrect_type(text); | ||
| 608 | -#else | ||
| 609 | - std::abort(); | ||
| 610 | -#endif | 611 | + throw_or_mimic<argument_incorrect_type>(text); |
| 611 | } | 612 | } |
| 612 | 613 | ||
| 613 | US next = result * base + digit; | 614 | US next = result * base + digit; |
| 614 | if (result > next) | 615 | if (result > next) |
| 615 | { | 616 | { |
| 616 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 617 | - throw argument_incorrect_type(text); | ||
| 618 | -#else | ||
| 619 | - std::abort(); | ||
| 620 | -#endif | 617 | + throw_or_mimic<argument_incorrect_type>(text); |
| 621 | } | 618 | } |
| 622 | 619 | ||
| 623 | result = next; | 620 | result = next; |
| @@ -643,11 +640,7 @@ namespace cxxopts | @@ -643,11 +640,7 @@ namespace cxxopts | ||
| 643 | std::stringstream in(text); | 640 | std::stringstream in(text); |
| 644 | in >> value; | 641 | in >> value; |
| 645 | if (!in) { | 642 | if (!in) { |
| 646 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 647 | - throw argument_incorrect_type(text); | ||
| 648 | -#else | ||
| 649 | - std::abort(); | ||
| 650 | -#endif | 643 | + throw_or_mimic<argument_incorrect_type>(text); |
| 651 | } | 644 | } |
| 652 | } | 645 | } |
| 653 | 646 | ||
| @@ -727,11 +720,7 @@ namespace cxxopts | @@ -727,11 +720,7 @@ namespace cxxopts | ||
| 727 | return; | 720 | return; |
| 728 | } | 721 | } |
| 729 | 722 | ||
| 730 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 731 | - throw argument_incorrect_type(text); | ||
| 732 | -#else | ||
| 733 | - std::abort(); | ||
| 734 | -#endif | 723 | + throw_or_mimic<argument_incorrect_type>(text); |
| 735 | } | 724 | } |
| 736 | 725 | ||
| 737 | inline | 726 | inline |
| @@ -1108,11 +1097,7 @@ namespace cxxopts | @@ -1108,11 +1097,7 @@ namespace cxxopts | ||
| 1108 | as() const | 1097 | as() const |
| 1109 | { | 1098 | { |
| 1110 | if (m_value == nullptr) { | 1099 | if (m_value == nullptr) { |
| 1111 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1112 | - throw std::domain_error("No value"); | ||
| 1113 | -#else | ||
| 1114 | - std::abort(); | ||
| 1115 | -#endif | 1100 | + throw_or_mimic<std::domain_error>("No value"); |
| 1116 | } | 1101 | } |
| 1117 | 1102 | ||
| 1118 | #ifdef CXXOPTS_NO_RTTI | 1103 | #ifdef CXXOPTS_NO_RTTI |
| @@ -1207,11 +1192,7 @@ namespace cxxopts | @@ -1207,11 +1192,7 @@ namespace cxxopts | ||
| 1207 | 1192 | ||
| 1208 | if (iter == m_options->end()) | 1193 | if (iter == m_options->end()) |
| 1209 | { | 1194 | { |
| 1210 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1211 | - throw option_not_present_exception(option); | ||
| 1212 | -#else | ||
| 1213 | - std::abort(); | ||
| 1214 | -#endif | 1195 | + throw_or_mimic<option_not_present_exception>(option); |
| 1215 | } | 1196 | } |
| 1216 | 1197 | ||
| 1217 | auto riter = m_results.find(iter->second); | 1198 | auto riter = m_results.find(iter->second); |
| @@ -1269,8 +1250,8 @@ namespace cxxopts | @@ -1269,8 +1250,8 @@ namespace cxxopts | ||
| 1269 | 1250 | ||
| 1270 | std::vector<KeyValue> m_sequential; | 1251 | std::vector<KeyValue> m_sequential; |
| 1271 | }; | 1252 | }; |
| 1272 | - | ||
| 1273 | - struct Option | 1253 | + |
| 1254 | + struct Option | ||
| 1274 | { | 1255 | { |
| 1275 | Option | 1256 | Option |
| 1276 | ( | 1257 | ( |
| @@ -1290,7 +1271,7 @@ namespace cxxopts | @@ -1290,7 +1271,7 @@ namespace cxxopts | ||
| 1290 | std::string desc_; | 1271 | std::string desc_; |
| 1291 | std::shared_ptr<const Value> value_; | 1272 | std::shared_ptr<const Value> value_; |
| 1292 | std::string arg_help_; | 1273 | std::string arg_help_; |
| 1293 | - }; | 1274 | + }; |
| 1294 | 1275 | ||
| 1295 | class Options | 1276 | class Options |
| 1296 | { | 1277 | { |
| @@ -1343,20 +1324,20 @@ namespace cxxopts | @@ -1343,20 +1324,20 @@ namespace cxxopts | ||
| 1343 | 1324 | ||
| 1344 | OptionAdder | 1325 | OptionAdder |
| 1345 | add_options(std::string group = ""); | 1326 | add_options(std::string group = ""); |
| 1346 | - | ||
| 1347 | - void | 1327 | + |
| 1328 | + void | ||
| 1348 | add_options | 1329 | add_options |
| 1349 | - ( | ||
| 1350 | - const std::string& group, | ||
| 1351 | - std::initializer_list<Option> options | ||
| 1352 | - ); | ||
| 1353 | - | ||
| 1354 | - void | ||
| 1355 | - add_option | ||
| 1356 | - ( | ||
| 1357 | - const std::string& group, | ||
| 1358 | - const Option& option | ||
| 1359 | - ); | 1330 | + ( |
| 1331 | + const std::string& group, | ||
| 1332 | + std::initializer_list<Option> options | ||
| 1333 | + ); | ||
| 1334 | + | ||
| 1335 | + void | ||
| 1336 | + add_option | ||
| 1337 | + ( | ||
| 1338 | + const std::string& group, | ||
| 1339 | + const Option& option | ||
| 1340 | + ); | ||
| 1360 | 1341 | ||
| 1361 | void | 1342 | void |
| 1362 | add_option | 1343 | add_option |
| @@ -1597,15 +1578,15 @@ ParseResult::ParseResult | @@ -1597,15 +1578,15 @@ ParseResult::ParseResult | ||
| 1597 | } | 1578 | } |
| 1598 | 1579 | ||
| 1599 | inline | 1580 | inline |
| 1600 | -void | 1581 | +void |
| 1601 | Options::add_options | 1582 | Options::add_options |
| 1602 | ( | 1583 | ( |
| 1603 | const std::string &group, | 1584 | const std::string &group, |
| 1604 | std::initializer_list<Option> options | 1585 | std::initializer_list<Option> options |
| 1605 | -) | 1586 | +) |
| 1606 | { | 1587 | { |
| 1607 | OptionAdder option_adder(*this, group); | 1588 | OptionAdder option_adder(*this, group); |
| 1608 | - for (const auto &option: options) | 1589 | + for (const auto &option: options) |
| 1609 | { | 1590 | { |
| 1610 | option_adder(option.opts_, option.desc_, option.value_, option.arg_help_); | 1591 | option_adder(option.opts_, option.desc_, option.value_, option.arg_help_); |
| 1611 | } | 1592 | } |
| @@ -1633,11 +1614,7 @@ OptionAdder::operator() | @@ -1633,11 +1614,7 @@ OptionAdder::operator() | ||
| 1633 | 1614 | ||
| 1634 | if (result.empty()) | 1615 | if (result.empty()) |
| 1635 | { | 1616 | { |
| 1636 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1637 | - throw invalid_option_format_error(opts); | ||
| 1638 | -#else | ||
| 1639 | - std::abort(); | ||
| 1640 | -#endif | 1617 | + throw_or_mimic<invalid_option_format_error>(opts); |
| 1641 | } | 1618 | } |
| 1642 | 1619 | ||
| 1643 | const auto& short_match = result[2]; | 1620 | const auto& short_match = result[2]; |
| @@ -1645,18 +1622,10 @@ OptionAdder::operator() | @@ -1645,18 +1622,10 @@ OptionAdder::operator() | ||
| 1645 | 1622 | ||
| 1646 | if (!short_match.length() && !long_match.length()) | 1623 | if (!short_match.length() && !long_match.length()) |
| 1647 | { | 1624 | { |
| 1648 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1649 | - throw invalid_option_format_error(opts); | ||
| 1650 | -#else | ||
| 1651 | - std::abort(); | ||
| 1652 | -#endif | 1625 | + throw_or_mimic<invalid_option_format_error>(opts); |
| 1653 | } else if (long_match.length() == 1 && short_match.length()) | 1626 | } else if (long_match.length() == 1 && short_match.length()) |
| 1654 | { | 1627 | { |
| 1655 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1656 | - throw invalid_option_format_error(opts); | ||
| 1657 | -#else | ||
| 1658 | - std::abort(); | ||
| 1659 | -#endif | 1628 | + throw_or_mimic<invalid_option_format_error>(opts); |
| 1660 | } | 1629 | } |
| 1661 | 1630 | ||
| 1662 | auto option_names = [] | 1631 | auto option_names = [] |
| @@ -1729,11 +1698,7 @@ ParseResult::checked_parse_arg | @@ -1729,11 +1698,7 @@ ParseResult::checked_parse_arg | ||
| 1729 | } | 1698 | } |
| 1730 | else | 1699 | else |
| 1731 | { | 1700 | { |
| 1732 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1733 | - throw missing_argument_exception(name); | ||
| 1734 | -#else | ||
| 1735 | - std::abort(); | ||
| 1736 | -#endif | 1701 | + throw_or_mimic<missing_argument_exception>(name); |
| 1737 | } | 1702 | } |
| 1738 | } | 1703 | } |
| 1739 | else | 1704 | else |
| @@ -1758,11 +1723,7 @@ ParseResult::add_to_option(const std::string& option, const std::string& arg) | @@ -1758,11 +1723,7 @@ ParseResult::add_to_option(const std::string& option, const std::string& arg) | ||
| 1758 | 1723 | ||
| 1759 | if (iter == m_options->end()) | 1724 | if (iter == m_options->end()) |
| 1760 | { | 1725 | { |
| 1761 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1762 | - throw option_not_exists_exception(option); | ||
| 1763 | -#else | ||
| 1764 | - std::abort(); | ||
| 1765 | -#endif | 1726 | + throw_or_mimic<option_not_exists_exception>(option); |
| 1766 | } | 1727 | } |
| 1767 | 1728 | ||
| 1768 | parse_option(iter->second, option, arg); | 1729 | parse_option(iter->second, option, arg); |
| @@ -1800,11 +1761,7 @@ ParseResult::consume_positional(std::string a) | @@ -1800,11 +1761,7 @@ ParseResult::consume_positional(std::string a) | ||
| 1800 | } | 1761 | } |
| 1801 | else | 1762 | else |
| 1802 | { | 1763 | { |
| 1803 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1804 | - throw option_not_exists_exception(*m_next_positional); | ||
| 1805 | -#else | ||
| 1806 | - std::abort(); | ||
| 1807 | -#endif | 1764 | + throw_or_mimic<option_not_exists_exception>(*m_next_positional); |
| 1808 | } | 1765 | } |
| 1809 | } | 1766 | } |
| 1810 | 1767 | ||
| @@ -1872,11 +1829,7 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1872,11 +1829,7 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1872 | // but if it starts with a `-`, then it's an error | 1829 | // but if it starts with a `-`, then it's an error |
| 1873 | if (argv[current][0] == '-' && argv[current][1] != '\0') { | 1830 | if (argv[current][0] == '-' && argv[current][1] != '\0') { |
| 1874 | if (!m_allow_unrecognised) { | 1831 | if (!m_allow_unrecognised) { |
| 1875 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1876 | - throw option_syntax_exception(argv[current]); | ||
| 1877 | -#else | ||
| 1878 | - std::abort(); | ||
| 1879 | -#endif | 1832 | + throw_or_mimic<option_syntax_exception>(argv[current]); |
| 1880 | } | 1833 | } |
| 1881 | } | 1834 | } |
| 1882 | 1835 | ||
| @@ -1913,11 +1866,7 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1913,11 +1866,7 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1913 | else | 1866 | else |
| 1914 | { | 1867 | { |
| 1915 | //error | 1868 | //error |
| 1916 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1917 | - throw option_not_exists_exception(name); | ||
| 1918 | -#else | ||
| 1919 | - std::abort(); | ||
| 1920 | -#endif | 1869 | + throw_or_mimic<option_not_exists_exception>(name); |
| 1921 | } | 1870 | } |
| 1922 | } | 1871 | } |
| 1923 | 1872 | ||
| @@ -1935,11 +1884,7 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1935,11 +1884,7 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1935 | else | 1884 | else |
| 1936 | { | 1885 | { |
| 1937 | //error | 1886 | //error |
| 1938 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1939 | - throw option_requires_argument_exception(name); | ||
| 1940 | -#else | ||
| 1941 | - std::abort(); | ||
| 1942 | -#endif | 1887 | + throw_or_mimic<option_requires_argument_exception>(name); |
| 1943 | } | 1888 | } |
| 1944 | } | 1889 | } |
| 1945 | } | 1890 | } |
| @@ -1962,11 +1907,7 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1962,11 +1907,7 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1962 | else | 1907 | else |
| 1963 | { | 1908 | { |
| 1964 | //error | 1909 | //error |
| 1965 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 1966 | - throw option_not_exists_exception(name); | ||
| 1967 | -#else | ||
| 1968 | - std::abort(); | ||
| 1969 | -#endif | 1910 | + throw_or_mimic<option_not_exists_exception>(name); |
| 1970 | } | 1911 | } |
| 1971 | } | 1912 | } |
| 1972 | 1913 | ||
| @@ -2033,7 +1974,7 @@ Options::add_option | @@ -2033,7 +1974,7 @@ Options::add_option | ||
| 2033 | const Option& option | 1974 | const Option& option |
| 2034 | ) | 1975 | ) |
| 2035 | { | 1976 | { |
| 2036 | - add_options(group, {option}); | 1977 | + add_options(group, {option}); |
| 2037 | } | 1978 | } |
| 2038 | 1979 | ||
| 2039 | inline | 1980 | inline |
| @@ -2084,11 +2025,7 @@ Options::add_one_option | @@ -2084,11 +2025,7 @@ Options::add_one_option | ||
| 2084 | 2025 | ||
| 2085 | if (!in.second) | 2026 | if (!in.second) |
| 2086 | { | 2027 | { |
| 2087 | -#ifndef CXXOPTS_NO_EXCEPTIONS | ||
| 2088 | - throw option_exists_error(option); | ||
| 2089 | -#else | ||
| 2090 | - std::abort(); | ||
| 2091 | -#endif | 2028 | + throw_or_mimic<option_exists_error>(option); |
| 2092 | } | 2029 | } |
| 2093 | } | 2030 | } |
| 2094 | 2031 |