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.
This commit is contained in:
Jarryd Beck 2018-11-08 18:17:33 +11:00
parent b528324107
commit c713b44d92
2 changed files with 38 additions and 20 deletions

View File

@ -1110,7 +1110,9 @@ namespace cxxopts
public:
ParseResult(
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&,
const std::shared_ptr<
std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
>,
std::vector<std::string>,
bool allow_unrecognised,
int&, char**&);
@ -1118,8 +1120,8 @@ namespace cxxopts
size_t
count(const std::string& o) const
{
auto iter = m_options.find(o);
if (iter == m_options.end())
auto iter = m_options->find(o);
if (iter == m_options->end())
{
return 0;
}
@ -1132,9 +1134,9 @@ namespace cxxopts
const OptionValue&
operator[](const std::string& option) const
{
auto iter = m_options.find(option);
auto iter = m_options->find(option);
if (iter == m_options.end())
if (iter == m_options->end())
{
throw option_not_present_exception(option);
}
@ -1182,8 +1184,9 @@ namespace cxxopts
const std::string& name
);
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
&m_options;
const std::shared_ptr<
std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
> m_options;
std::vector<std::string> m_positional;
std::vector<std::string>::iterator m_next_positional;
std::unordered_set<std::string> m_positional_set;
@ -1196,6 +1199,8 @@ namespace cxxopts
class Options
{
typedef std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
OptionMap;
public:
Options(std::string program, std::string help_string = "")
@ -1205,6 +1210,7 @@ namespace cxxopts
, m_positional_help("positional parameters")
, m_show_positional(false)
, m_allow_unrecognised(false)
, m_options(std::make_shared<OptionMap>())
, m_next_positional(m_positional.end())
{
}
@ -1308,7 +1314,7 @@ namespace cxxopts
bool m_show_positional;
bool m_allow_unrecognised;
std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options;
std::shared_ptr<OptionMap> m_options;
std::vector<std::string> m_positional;
std::vector<std::string>::iterator m_next_positional;
std::unordered_set<std::string> m_positional_set;
@ -1466,7 +1472,9 @@ namespace cxxopts
inline
ParseResult::ParseResult
(
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options,
const std::shared_ptr<
std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
> options,
std::vector<std::string> positional,
bool allow_unrecognised,
int& argc, char**& argv
@ -1606,9 +1614,9 @@ inline
void
ParseResult::add_to_option(const std::string& option, const std::string& arg)
{
auto iter = m_options.find(option);
auto iter = m_options->find(option);
if (iter == m_options.end())
if (iter == m_options->end())
{
throw option_not_exists_exception(option);
}
@ -1622,8 +1630,8 @@ ParseResult::consume_positional(std::string a)
{
while (m_next_positional != m_positional.end())
{
auto iter = m_options.find(*m_next_positional);
if (iter != m_options.end())
auto iter = m_options->find(*m_next_positional);
if (iter != m_options->end())
{
auto& result = m_results[iter->second];
if (!iter->second->value().is_container())
@ -1737,9 +1745,9 @@ ParseResult::parse(int& argc, char**& argv)
for (std::size_t i = 0; i != s.size(); ++i)
{
std::string name(1, s[i]);
auto iter = m_options.find(name);
auto iter = m_options->find(name);
if (iter == m_options.end())
if (iter == m_options->end())
{
if (m_allow_unrecognised)
{
@ -1774,9 +1782,9 @@ ParseResult::parse(int& argc, char**& argv)
{
const std::string& name = result[1];
auto iter = m_options.find(name);
auto iter = m_options->find(name);
if (iter == m_options.end())
if (iter == m_options->end())
{
if (m_allow_unrecognised)
{
@ -1814,7 +1822,7 @@ ParseResult::parse(int& argc, char**& argv)
++current;
}
for (auto& opt : m_options)
for (auto& opt : *m_options)
{
auto& detail = opt.second;
auto& value = detail->value();
@ -1892,7 +1900,7 @@ Options::add_one_option
std::shared_ptr<OptionDetails> details
)
{
auto in = m_options.emplace(option, details);
auto in = m_options->emplace(option, details);
if (!in.second)
{

View File

@ -26,7 +26,8 @@ THE SOFTWARE.
#include "cxxopts.hpp"
int main(int argc, char* argv[])
cxxopts::ParseResult
parse(int argc, char* argv[])
{
try
{
@ -131,11 +132,20 @@ int main(int argc, char* argv[])
std::cout << "Arguments remain = " << argc << std::endl;
return result;
} catch (const cxxopts::OptionException& e)
{
std::cout << "error parsing options: " << e.what() << std::endl;
exit(1);
}
}
int main(int argc, char* argv[])
{
auto result = parse(argc, argv);
auto arguments = result.arguments();
std::cout << "Saw " << arguments.size() << " arguments" << std::endl;
return 0;
}