Commit 34784b01f7bdb989e56f268b632091a8a8738906

Authored by charlydelta
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&amp; option, const std::string&amp; 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&amp; argc, char**&amp; 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&amp; argc, char**&amp; 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&amp; argc, char**&amp; 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&amp; argc, char**&amp; 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  
... ...