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 | 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 | 490 | namespace values |
| 471 | 491 | { |
| 472 | 492 | namespace |
| ... | ... | @@ -495,22 +515,14 @@ namespace cxxopts |
| 495 | 515 | { |
| 496 | 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 | 521 | else |
| 506 | 522 | { |
| 507 | 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 | 556 | |
| 545 | 557 | template <typename R, typename T> |
| 546 | 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 | 565 | template <typename T> |
| ... | ... | @@ -562,11 +571,7 @@ namespace cxxopts |
| 562 | 571 | |
| 563 | 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 | 577 | if (match.length(4) > 0) |
| ... | ... | @@ -603,21 +608,13 @@ namespace cxxopts |
| 603 | 608 | } |
| 604 | 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 | 614 | US next = result * base + digit; |
| 614 | 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 | 620 | result = next; |
| ... | ... | @@ -643,11 +640,7 @@ namespace cxxopts |
| 643 | 640 | std::stringstream in(text); |
| 644 | 641 | in >> value; |
| 645 | 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 | 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 | 726 | inline |
| ... | ... | @@ -1108,11 +1097,7 @@ namespace cxxopts |
| 1108 | 1097 | as() const |
| 1109 | 1098 | { |
| 1110 | 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 | 1103 | #ifdef CXXOPTS_NO_RTTI |
| ... | ... | @@ -1207,11 +1192,7 @@ namespace cxxopts |
| 1207 | 1192 | |
| 1208 | 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 | 1198 | auto riter = m_results.find(iter->second); |
| ... | ... | @@ -1269,8 +1250,8 @@ namespace cxxopts |
| 1269 | 1250 | |
| 1270 | 1251 | std::vector<KeyValue> m_sequential; |
| 1271 | 1252 | }; |
| 1272 | - | |
| 1273 | - struct Option | |
| 1253 | + | |
| 1254 | + struct Option | |
| 1274 | 1255 | { |
| 1275 | 1256 | Option |
| 1276 | 1257 | ( |
| ... | ... | @@ -1290,7 +1271,7 @@ namespace cxxopts |
| 1290 | 1271 | std::string desc_; |
| 1291 | 1272 | std::shared_ptr<const Value> value_; |
| 1292 | 1273 | std::string arg_help_; |
| 1293 | - }; | |
| 1274 | + }; | |
| 1294 | 1275 | |
| 1295 | 1276 | class Options |
| 1296 | 1277 | { |
| ... | ... | @@ -1343,20 +1324,20 @@ namespace cxxopts |
| 1343 | 1324 | |
| 1344 | 1325 | OptionAdder |
| 1345 | 1326 | add_options(std::string group = ""); |
| 1346 | - | |
| 1347 | - void | |
| 1327 | + | |
| 1328 | + void | |
| 1348 | 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 | 1342 | void |
| 1362 | 1343 | add_option |
| ... | ... | @@ -1597,15 +1578,15 @@ ParseResult::ParseResult |
| 1597 | 1578 | } |
| 1598 | 1579 | |
| 1599 | 1580 | inline |
| 1600 | -void | |
| 1581 | +void | |
| 1601 | 1582 | Options::add_options |
| 1602 | 1583 | ( |
| 1603 | 1584 | const std::string &group, |
| 1604 | 1585 | std::initializer_list<Option> options |
| 1605 | -) | |
| 1586 | +) | |
| 1606 | 1587 | { |
| 1607 | 1588 | OptionAdder option_adder(*this, group); |
| 1608 | - for (const auto &option: options) | |
| 1589 | + for (const auto &option: options) | |
| 1609 | 1590 | { |
| 1610 | 1591 | option_adder(option.opts_, option.desc_, option.value_, option.arg_help_); |
| 1611 | 1592 | } |
| ... | ... | @@ -1633,11 +1614,7 @@ OptionAdder::operator() |
| 1633 | 1614 | |
| 1634 | 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 | 1620 | const auto& short_match = result[2]; |
| ... | ... | @@ -1645,18 +1622,10 @@ OptionAdder::operator() |
| 1645 | 1622 | |
| 1646 | 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 | 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 | 1631 | auto option_names = [] |
| ... | ... | @@ -1729,11 +1698,7 @@ ParseResult::checked_parse_arg |
| 1729 | 1698 | } |
| 1730 | 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 | 1704 | else |
| ... | ... | @@ -1758,11 +1723,7 @@ ParseResult::add_to_option(const std::string& option, const std::string& arg) |
| 1758 | 1723 | |
| 1759 | 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 | 1729 | parse_option(iter->second, option, arg); |
| ... | ... | @@ -1800,11 +1761,7 @@ ParseResult::consume_positional(std::string a) |
| 1800 | 1761 | } |
| 1801 | 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 | 1829 | // but if it starts with a `-`, then it's an error |
| 1873 | 1830 | if (argv[current][0] == '-' && argv[current][1] != '\0') { |
| 1874 | 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 | 1866 | else |
| 1914 | 1867 | { |
| 1915 | 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 | 1884 | else |
| 1936 | 1885 | { |
| 1937 | 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 | 1907 | else |
| 1963 | 1908 | { |
| 1964 | 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 | 1974 | const Option& option |
| 2034 | 1975 | ) |
| 2035 | 1976 | { |
| 2036 | - add_options(group, {option}); | |
| 1977 | + add_options(group, {option}); | |
| 2037 | 1978 | } |
| 2038 | 1979 | |
| 2039 | 1980 | inline |
| ... | ... | @@ -2084,11 +2025,7 @@ Options::add_one_option |
| 2084 | 2025 | |
| 2085 | 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 | ... | ... |