Commit c713b44d92e4ea2569101fa6bdf60afa311b29a3

Authored by Jarryd Beck
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.
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&amp; argc, char**&amp; 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&amp; argc, char**&amp; 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&amp; argc, char**&amp; 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 }
... ...