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,7 +1110,9 @@ namespace cxxopts | ||
| 1110 | public: | 1110 | public: |
| 1111 | 1111 | ||
| 1112 | ParseResult( | 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 | std::vector<std::string>, | 1116 | std::vector<std::string>, |
| 1115 | bool allow_unrecognised, | 1117 | bool allow_unrecognised, |
| 1116 | int&, char**&); | 1118 | int&, char**&); |
| @@ -1118,8 +1120,8 @@ namespace cxxopts | @@ -1118,8 +1120,8 @@ namespace cxxopts | ||
| 1118 | size_t | 1120 | size_t |
| 1119 | count(const std::string& o) const | 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 | return 0; | 1126 | return 0; |
| 1125 | } | 1127 | } |
| @@ -1132,9 +1134,9 @@ namespace cxxopts | @@ -1132,9 +1134,9 @@ namespace cxxopts | ||
| 1132 | const OptionValue& | 1134 | const OptionValue& |
| 1133 | operator[](const std::string& option) const | 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 | throw option_not_present_exception(option); | 1141 | throw option_not_present_exception(option); |
| 1140 | } | 1142 | } |
| @@ -1182,8 +1184,9 @@ namespace cxxopts | @@ -1182,8 +1184,9 @@ namespace cxxopts | ||
| 1182 | const std::string& name | 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 | std::vector<std::string> m_positional; | 1190 | std::vector<std::string> m_positional; |
| 1188 | std::vector<std::string>::iterator m_next_positional; | 1191 | std::vector<std::string>::iterator m_next_positional; |
| 1189 | std::unordered_set<std::string> m_positional_set; | 1192 | std::unordered_set<std::string> m_positional_set; |
| @@ -1196,6 +1199,8 @@ namespace cxxopts | @@ -1196,6 +1199,8 @@ namespace cxxopts | ||
| 1196 | 1199 | ||
| 1197 | class Options | 1200 | class Options |
| 1198 | { | 1201 | { |
| 1202 | + typedef std::unordered_map<std::string, std::shared_ptr<OptionDetails>> | ||
| 1203 | + OptionMap; | ||
| 1199 | public: | 1204 | public: |
| 1200 | 1205 | ||
| 1201 | Options(std::string program, std::string help_string = "") | 1206 | Options(std::string program, std::string help_string = "") |
| @@ -1205,6 +1210,7 @@ namespace cxxopts | @@ -1205,6 +1210,7 @@ namespace cxxopts | ||
| 1205 | , m_positional_help("positional parameters") | 1210 | , m_positional_help("positional parameters") |
| 1206 | , m_show_positional(false) | 1211 | , m_show_positional(false) |
| 1207 | , m_allow_unrecognised(false) | 1212 | , m_allow_unrecognised(false) |
| 1213 | + , m_options(std::make_shared<OptionMap>()) | ||
| 1208 | , m_next_positional(m_positional.end()) | 1214 | , m_next_positional(m_positional.end()) |
| 1209 | { | 1215 | { |
| 1210 | } | 1216 | } |
| @@ -1308,7 +1314,7 @@ namespace cxxopts | @@ -1308,7 +1314,7 @@ namespace cxxopts | ||
| 1308 | bool m_show_positional; | 1314 | bool m_show_positional; |
| 1309 | bool m_allow_unrecognised; | 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 | std::vector<std::string> m_positional; | 1318 | std::vector<std::string> m_positional; |
| 1313 | std::vector<std::string>::iterator m_next_positional; | 1319 | std::vector<std::string>::iterator m_next_positional; |
| 1314 | std::unordered_set<std::string> m_positional_set; | 1320 | std::unordered_set<std::string> m_positional_set; |
| @@ -1466,7 +1472,9 @@ namespace cxxopts | @@ -1466,7 +1472,9 @@ namespace cxxopts | ||
| 1466 | inline | 1472 | inline |
| 1467 | ParseResult::ParseResult | 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 | std::vector<std::string> positional, | 1478 | std::vector<std::string> positional, |
| 1471 | bool allow_unrecognised, | 1479 | bool allow_unrecognised, |
| 1472 | int& argc, char**& argv | 1480 | int& argc, char**& argv |
| @@ -1606,9 +1614,9 @@ inline | @@ -1606,9 +1614,9 @@ inline | ||
| 1606 | void | 1614 | void |
| 1607 | ParseResult::add_to_option(const std::string& option, const std::string& arg) | 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 | throw option_not_exists_exception(option); | 1621 | throw option_not_exists_exception(option); |
| 1614 | } | 1622 | } |
| @@ -1622,8 +1630,8 @@ ParseResult::consume_positional(std::string a) | @@ -1622,8 +1630,8 @@ ParseResult::consume_positional(std::string a) | ||
| 1622 | { | 1630 | { |
| 1623 | while (m_next_positional != m_positional.end()) | 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 | auto& result = m_results[iter->second]; | 1636 | auto& result = m_results[iter->second]; |
| 1629 | if (!iter->second->value().is_container()) | 1637 | if (!iter->second->value().is_container()) |
| @@ -1737,9 +1745,9 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1737,9 +1745,9 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1737 | for (std::size_t i = 0; i != s.size(); ++i) | 1745 | for (std::size_t i = 0; i != s.size(); ++i) |
| 1738 | { | 1746 | { |
| 1739 | std::string name(1, s[i]); | 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 | if (m_allow_unrecognised) | 1752 | if (m_allow_unrecognised) |
| 1745 | { | 1753 | { |
| @@ -1774,9 +1782,9 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1774,9 +1782,9 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1774 | { | 1782 | { |
| 1775 | const std::string& name = result[1]; | 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 | if (m_allow_unrecognised) | 1789 | if (m_allow_unrecognised) |
| 1782 | { | 1790 | { |
| @@ -1814,7 +1822,7 @@ ParseResult::parse(int& argc, char**& argv) | @@ -1814,7 +1822,7 @@ ParseResult::parse(int& argc, char**& argv) | ||
| 1814 | ++current; | 1822 | ++current; |
| 1815 | } | 1823 | } |
| 1816 | 1824 | ||
| 1817 | - for (auto& opt : m_options) | 1825 | + for (auto& opt : *m_options) |
| 1818 | { | 1826 | { |
| 1819 | auto& detail = opt.second; | 1827 | auto& detail = opt.second; |
| 1820 | auto& value = detail->value(); | 1828 | auto& value = detail->value(); |
| @@ -1892,7 +1900,7 @@ Options::add_one_option | @@ -1892,7 +1900,7 @@ Options::add_one_option | ||
| 1892 | std::shared_ptr<OptionDetails> details | 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 | if (!in.second) | 1905 | if (!in.second) |
| 1898 | { | 1906 | { |
src/example.cpp
| @@ -26,7 +26,8 @@ THE SOFTWARE. | @@ -26,7 +26,8 @@ THE SOFTWARE. | ||
| 26 | 26 | ||
| 27 | #include "cxxopts.hpp" | 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 | try | 32 | try |
| 32 | { | 33 | { |
| @@ -131,11 +132,20 @@ int main(int argc, char* argv[]) | @@ -131,11 +132,20 @@ int main(int argc, char* argv[]) | ||
| 131 | 132 | ||
| 132 | std::cout << "Arguments remain = " << argc << std::endl; | 133 | std::cout << "Arguments remain = " << argc << std::endl; |
| 133 | 134 | ||
| 135 | + return result; | ||
| 136 | + | ||
| 134 | } catch (const cxxopts::OptionException& e) | 137 | } catch (const cxxopts::OptionException& e) |
| 135 | { | 138 | { |
| 136 | std::cout << "error parsing options: " << e.what() << std::endl; | 139 | std::cout << "error parsing options: " << e.what() << std::endl; |
| 137 | exit(1); | 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 | return 0; | 150 | return 0; |
| 141 | } | 151 | } |