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,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&amp; option, const std::string&amp; arg) @@ -1758,11 +1723,7 @@ ParseResult::add_to_option(const std::string&amp; option, const std::string&amp; 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&amp; argc, char**&amp; argv) @@ -1872,11 +1829,7 @@ ParseResult::parse(int&amp; argc, char**&amp; 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&amp; argc, char**&amp; argv) @@ -1913,11 +1866,7 @@ ParseResult::parse(int&amp; argc, char**&amp; 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&amp; argc, char**&amp; argv) @@ -1935,11 +1884,7 @@ ParseResult::parse(int&amp; argc, char**&amp; 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&amp; argc, char**&amp; argv) @@ -1962,11 +1907,7 @@ ParseResult::parse(int&amp; argc, char**&amp; 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