Commit c713b44d92e4ea2569101fa6bdf60afa311b29a3
1 parent
b5283241
Use a shared pointer for the options map
Fixes #132. Since the map of options is shared between Options and ParseResult, they should use a shared pointer instead of a reference so that ParseResult can be returned without referencing destroyed memory.
Showing
2 changed files
with
38 additions
and
20 deletions
include/cxxopts.hpp
| ... | ... | @@ -1110,7 +1110,9 @@ namespace cxxopts |
| 1110 | 1110 | public: |
| 1111 | 1111 | |
| 1112 | 1112 | ParseResult( |
| 1113 | - const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&, | |
| 1113 | + const std::shared_ptr< | |
| 1114 | + std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | |
| 1115 | + >, | |
| 1114 | 1116 | std::vector<std::string>, |
| 1115 | 1117 | bool allow_unrecognised, |
| 1116 | 1118 | int&, char**&); |
| ... | ... | @@ -1118,8 +1120,8 @@ namespace cxxopts |
| 1118 | 1120 | size_t |
| 1119 | 1121 | count(const std::string& o) const |
| 1120 | 1122 | { |
| 1121 | - auto iter = m_options.find(o); | |
| 1122 | - if (iter == m_options.end()) | |
| 1123 | + auto iter = m_options->find(o); | |
| 1124 | + if (iter == m_options->end()) | |
| 1123 | 1125 | { |
| 1124 | 1126 | return 0; |
| 1125 | 1127 | } |
| ... | ... | @@ -1132,9 +1134,9 @@ namespace cxxopts |
| 1132 | 1134 | const OptionValue& |
| 1133 | 1135 | operator[](const std::string& option) const |
| 1134 | 1136 | { |
| 1135 | - auto iter = m_options.find(option); | |
| 1137 | + auto iter = m_options->find(option); | |
| 1136 | 1138 | |
| 1137 | - if (iter == m_options.end()) | |
| 1139 | + if (iter == m_options->end()) | |
| 1138 | 1140 | { |
| 1139 | 1141 | throw option_not_present_exception(option); |
| 1140 | 1142 | } |
| ... | ... | @@ -1182,8 +1184,9 @@ namespace cxxopts |
| 1182 | 1184 | const std::string& name |
| 1183 | 1185 | ); |
| 1184 | 1186 | |
| 1185 | - const std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | |
| 1186 | - &m_options; | |
| 1187 | + const std::shared_ptr< | |
| 1188 | + std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | |
| 1189 | + > m_options; | |
| 1187 | 1190 | std::vector<std::string> m_positional; |
| 1188 | 1191 | std::vector<std::string>::iterator m_next_positional; |
| 1189 | 1192 | std::unordered_set<std::string> m_positional_set; |
| ... | ... | @@ -1196,6 +1199,8 @@ namespace cxxopts |
| 1196 | 1199 | |
| 1197 | 1200 | class Options |
| 1198 | 1201 | { |
| 1202 | + typedef std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | |
| 1203 | + OptionMap; | |
| 1199 | 1204 | public: |
| 1200 | 1205 | |
| 1201 | 1206 | Options(std::string program, std::string help_string = "") |
| ... | ... | @@ -1205,6 +1210,7 @@ namespace cxxopts |
| 1205 | 1210 | , m_positional_help("positional parameters") |
| 1206 | 1211 | , m_show_positional(false) |
| 1207 | 1212 | , m_allow_unrecognised(false) |
| 1213 | + , m_options(std::make_shared<OptionMap>()) | |
| 1208 | 1214 | , m_next_positional(m_positional.end()) |
| 1209 | 1215 | { |
| 1210 | 1216 | } |
| ... | ... | @@ -1308,7 +1314,7 @@ namespace cxxopts |
| 1308 | 1314 | bool m_show_positional; |
| 1309 | 1315 | bool m_allow_unrecognised; |
| 1310 | 1316 | |
| 1311 | - std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options; | |
| 1317 | + std::shared_ptr<OptionMap> m_options; | |
| 1312 | 1318 | std::vector<std::string> m_positional; |
| 1313 | 1319 | std::vector<std::string>::iterator m_next_positional; |
| 1314 | 1320 | std::unordered_set<std::string> m_positional_set; |
| ... | ... | @@ -1466,7 +1472,9 @@ namespace cxxopts |
| 1466 | 1472 | inline |
| 1467 | 1473 | ParseResult::ParseResult |
| 1468 | 1474 | ( |
| 1469 | - const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options, | |
| 1475 | + const std::shared_ptr< | |
| 1476 | + std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | |
| 1477 | + > options, | |
| 1470 | 1478 | std::vector<std::string> positional, |
| 1471 | 1479 | bool allow_unrecognised, |
| 1472 | 1480 | int& argc, char**& argv |
| ... | ... | @@ -1606,9 +1614,9 @@ inline |
| 1606 | 1614 | void |
| 1607 | 1615 | ParseResult::add_to_option(const std::string& option, const std::string& arg) |
| 1608 | 1616 | { |
| 1609 | - auto iter = m_options.find(option); | |
| 1617 | + auto iter = m_options->find(option); | |
| 1610 | 1618 | |
| 1611 | - if (iter == m_options.end()) | |
| 1619 | + if (iter == m_options->end()) | |
| 1612 | 1620 | { |
| 1613 | 1621 | throw option_not_exists_exception(option); |
| 1614 | 1622 | } |
| ... | ... | @@ -1622,8 +1630,8 @@ ParseResult::consume_positional(std::string a) |
| 1622 | 1630 | { |
| 1623 | 1631 | while (m_next_positional != m_positional.end()) |
| 1624 | 1632 | { |
| 1625 | - auto iter = m_options.find(*m_next_positional); | |
| 1626 | - if (iter != m_options.end()) | |
| 1633 | + auto iter = m_options->find(*m_next_positional); | |
| 1634 | + if (iter != m_options->end()) | |
| 1627 | 1635 | { |
| 1628 | 1636 | auto& result = m_results[iter->second]; |
| 1629 | 1637 | if (!iter->second->value().is_container()) |
| ... | ... | @@ -1737,9 +1745,9 @@ ParseResult::parse(int& argc, char**& argv) |
| 1737 | 1745 | for (std::size_t i = 0; i != s.size(); ++i) |
| 1738 | 1746 | { |
| 1739 | 1747 | std::string name(1, s[i]); |
| 1740 | - auto iter = m_options.find(name); | |
| 1748 | + auto iter = m_options->find(name); | |
| 1741 | 1749 | |
| 1742 | - if (iter == m_options.end()) | |
| 1750 | + if (iter == m_options->end()) | |
| 1743 | 1751 | { |
| 1744 | 1752 | if (m_allow_unrecognised) |
| 1745 | 1753 | { |
| ... | ... | @@ -1774,9 +1782,9 @@ ParseResult::parse(int& argc, char**& argv) |
| 1774 | 1782 | { |
| 1775 | 1783 | const std::string& name = result[1]; |
| 1776 | 1784 | |
| 1777 | - auto iter = m_options.find(name); | |
| 1785 | + auto iter = m_options->find(name); | |
| 1778 | 1786 | |
| 1779 | - if (iter == m_options.end()) | |
| 1787 | + if (iter == m_options->end()) | |
| 1780 | 1788 | { |
| 1781 | 1789 | if (m_allow_unrecognised) |
| 1782 | 1790 | { |
| ... | ... | @@ -1814,7 +1822,7 @@ ParseResult::parse(int& argc, char**& argv) |
| 1814 | 1822 | ++current; |
| 1815 | 1823 | } |
| 1816 | 1824 | |
| 1817 | - for (auto& opt : m_options) | |
| 1825 | + for (auto& opt : *m_options) | |
| 1818 | 1826 | { |
| 1819 | 1827 | auto& detail = opt.second; |
| 1820 | 1828 | auto& value = detail->value(); |
| ... | ... | @@ -1892,7 +1900,7 @@ Options::add_one_option |
| 1892 | 1900 | std::shared_ptr<OptionDetails> details |
| 1893 | 1901 | ) |
| 1894 | 1902 | { |
| 1895 | - auto in = m_options.emplace(option, details); | |
| 1903 | + auto in = m_options->emplace(option, details); | |
| 1896 | 1904 | |
| 1897 | 1905 | if (!in.second) |
| 1898 | 1906 | { | ... | ... |
src/example.cpp
| ... | ... | @@ -26,7 +26,8 @@ THE SOFTWARE. |
| 26 | 26 | |
| 27 | 27 | #include "cxxopts.hpp" |
| 28 | 28 | |
| 29 | -int main(int argc, char* argv[]) | |
| 29 | +cxxopts::ParseResult | |
| 30 | +parse(int argc, char* argv[]) | |
| 30 | 31 | { |
| 31 | 32 | try |
| 32 | 33 | { |
| ... | ... | @@ -131,11 +132,20 @@ int main(int argc, char* argv[]) |
| 131 | 132 | |
| 132 | 133 | std::cout << "Arguments remain = " << argc << std::endl; |
| 133 | 134 | |
| 135 | + return result; | |
| 136 | + | |
| 134 | 137 | } catch (const cxxopts::OptionException& e) |
| 135 | 138 | { |
| 136 | 139 | std::cout << "error parsing options: " << e.what() << std::endl; |
| 137 | 140 | exit(1); |
| 138 | 141 | } |
| 142 | +} | |
| 143 | + | |
| 144 | +int main(int argc, char* argv[]) | |
| 145 | +{ | |
| 146 | + auto result = parse(argc, argv); | |
| 147 | + auto arguments = result.arguments(); | |
| 148 | + std::cout << "Saw " << arguments.size() << " arguments" << std::endl; | |
| 139 | 149 | |
| 140 | 150 | return 0; |
| 141 | 151 | } | ... | ... |