Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Shared pointer instead of raw pointer #109

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions include/boost/program_options/detail/value_semantic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// This file defines template functions that are declared in
// ../value_semantic.hpp.

#include <boost/smart_ptr/make_shared.hpp>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a downside to using the shared pointers instead of raw pointers. If you include program_options, it will include make_shared (and later on in this pull request enable_shared_from_this)

#include <boost/throw_exception.hpp>

// forward declaration
Expand Down Expand Up @@ -185,34 +186,34 @@ namespace boost { namespace program_options {
}

template<class T>
typed_value<T>*
shared_ptr<typed_value<T> >
value()
{
// Explicit qualification is vc6 workaround.
return boost::program_options::value<T>(0);
}

template<class T>
typed_value<T>*
shared_ptr<typed_value<T> >
value(T* v)
{
typed_value<T>* r = new typed_value<T>(v);
shared_ptr<typed_value<T> > r = boost::make_shared<typed_value<T> >(v);

return r;
}

template<class T>
typed_value<T, wchar_t>*
shared_ptr<typed_value<T, wchar_t> >
wvalue()
{
return wvalue<T>(0);
}

template<class T>
typed_value<T, wchar_t>*
shared_ptr<typed_value<T, wchar_t> >
wvalue(T* v)
{
typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
shared_ptr<typed_value<T, wchar_t> > r = boost::make_shared<typed_value<T, wchar_t> >(v);

return r;
}
Expand Down
13 changes: 11 additions & 2 deletions include/boost/program_options/options_description.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ namespace program_options {
after \-- short name.
*/
option_description(const char* name,
const value_semantic* s);
shared_ptr<const value_semantic> s);

/** Initializes the class with the passed data.
*/
option_description(const char* name,
const value_semantic* s,
shared_ptr<const value_semantic> s,
const char* description);

virtual ~option_description();
Expand Down Expand Up @@ -167,6 +167,15 @@ namespace program_options {
operator()(const char* name,
const char* description);

options_description_easy_init&
operator()(const char* name,
shared_ptr<const value_semantic> s);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the functions that used const value_semantic* s for backwards compatibility. The last thing I want to do is break someone's code that depends on it.


options_description_easy_init&
operator()(const char* name,
shared_ptr<const value_semantic> s,
const char* description);

options_description_easy_init&
operator()(const char* name,
const value_semantic* s);
Expand Down
56 changes: 29 additions & 27 deletions include/boost/program_options/value_semantic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/any.hpp>
#include <boost/function/function1.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/smart_ptr/enable_shared_from_this.hpp>

#include <string>
#include <vector>
Expand Down Expand Up @@ -178,7 +179,8 @@ namespace boost { namespace program_options {

/** Class which handles value of a specific type. */
template<class T, class charT = char>
class typed_value : public value_semantic_codecvt_helper<charT>
class typed_value : public enable_shared_from_this<typed_value<T, charT> >,
public value_semantic_codecvt_helper<charT>
#ifndef BOOST_NO_RTTI
, public typed_value_base
#endif
Expand All @@ -196,11 +198,11 @@ namespace boost { namespace program_options {
if none is explicitly specified. The type 'T' should
provide operator<< for ostream.
*/
typed_value* default_value(const T& v)
shared_ptr<typed_value> default_value(const T& v)
{
m_default_value = boost::any(v);
m_default_value_as_text = boost::lexical_cast<std::string>(v);
return this;
return this->shared_from_this();
}

/** Specifies default value, which will be used
Expand All @@ -209,30 +211,30 @@ namespace boost { namespace program_options {
but textual representation of default value must be provided
by the user.
*/
typed_value* default_value(const T& v, const std::string& textual)
shared_ptr<typed_value> default_value(const T& v, const std::string& textual)
{
m_default_value = boost::any(v);
m_default_value_as_text = textual;
return this;
return this->shared_from_this();
}

/** Specifies an implicit value, which will be used
if the option is given, but without an adjacent value.
Using this implies that an explicit value is optional,
*/
typed_value* implicit_value(const T &v)
shared_ptr<typed_value> implicit_value(const T &v)
{
m_implicit_value = boost::any(v);
m_implicit_value_as_text =
boost::lexical_cast<std::string>(v);
return this;
return this->shared_from_this();
}

/** Specifies the name used to to the value in help message. */
typed_value* value_name(const std::string& name)
shared_ptr<typed_value> value_name(const std::string& name)
{
m_value_name = name;
return this;
return this->shared_from_this();
}

/** Specifies an implicit value, which will be used
Expand All @@ -245,36 +247,36 @@ namespace boost { namespace program_options {
operator<< for ostream, but textual representation of default
value must be provided by the user.
*/
typed_value* implicit_value(const T &v, const std::string& textual)
shared_ptr<typed_value> implicit_value(const T &v, const std::string& textual)
{
m_implicit_value = boost::any(v);
m_implicit_value_as_text = textual;
return this;
return this->shared_from_this();
}

/** Specifies a function to be called when the final value
is determined. */
typed_value* notifier(function1<void, const T&> f)
shared_ptr<typed_value> notifier(function1<void, const T&> f)
{
m_notifier = f;
return this;
return this->shared_from_this();
}

/** Specifies that the value is composing. See the 'is_composing'
method for explanation.
*/
typed_value* composing()
shared_ptr<typed_value> composing()
{
m_composing = true;
return this;
return this->shared_from_this();
}

/** Specifies that the value can span multiple tokens.
*/
typed_value* multitoken()
shared_ptr<typed_value> multitoken()
{
m_multitoken = true;
return this;
return this->shared_from_this();
}

/** Specifies that no tokens may be provided as the value of
Expand All @@ -284,17 +286,17 @@ namespace boost { namespace program_options {
'implicit_value' method should be also used. In most
cases, you can use the 'bool_switch' function instead of
using this method. */
typed_value* zero_tokens()
shared_ptr<typed_value> zero_tokens()
{
m_zero_tokens = true;
return this;
return this->shared_from_this();
}

/** Specifies that the value must occur. */
typed_value* required()
shared_ptr<typed_value> required()
{
m_required = true;
return this;
return this->shared_from_this();
}

public: // value semantic overrides
Expand Down Expand Up @@ -381,39 +383,39 @@ namespace boost { namespace program_options {
value of option into program variable.
*/
template<class T>
typed_value<T>*
shared_ptr<typed_value<T> >
value();

/** @overload
*/
template<class T>
typed_value<T>*
shared_ptr<typed_value<T> >
value(T* v);

/** Creates a typed_value<T> instance. This function is the primary
method to create value_semantic instance for a specific type, which
can later be passed to 'option_description' constructor.
*/
template<class T>
typed_value<T, wchar_t>*
shared_ptr<typed_value<T, wchar_t> >
wvalue();

/** @overload
*/
template<class T>
typed_value<T, wchar_t>*
shared_ptr<typed_value<T, wchar_t> >
wvalue(T* v);

/** Works the same way as the 'value<bool>' function, but the created
value_semantic won't accept any explicit value. So, if the option
is present on the command line, the value will be 'true'.
*/
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool> >
bool_switch();

/** @overload
*/
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool> >
bool_switch(bool* v);

}}
Expand Down
28 changes: 23 additions & 5 deletions src/options_description.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// FIXME: this is only to get multiple_occurrences class
// should move that to a separate headers.
#include <boost/program_options/parsers.hpp>
#include <boost/smart_ptr/make_shared.hpp>


#include <boost/lexical_cast.hpp>
Expand Down Expand Up @@ -50,7 +51,7 @@ namespace boost { namespace program_options {

option_description::
option_description(const char* names,
const value_semantic* s)
shared_ptr<const value_semantic> s)
: m_value_semantic(s)
{
this->set_names(names);
Expand All @@ -59,7 +60,7 @@ namespace boost { namespace program_options {

option_description::
option_description(const char* names,
const value_semantic* s,
shared_ptr<const value_semantic> s,
const char* description)
: m_description(description), m_value_semantic(s)
{
Expand Down Expand Up @@ -266,7 +267,7 @@ namespace boost { namespace program_options {
// no value can be specified on command line.
// FIXME: does not look exception-safe
shared_ptr<option_description> d(
new option_description(name, new untyped_value(true), description));
new option_description(name, boost::make_shared<untyped_value>(true), description));

owner->add(d);
return *this;
Expand All @@ -275,7 +276,7 @@ namespace boost { namespace program_options {
options_description_easy_init&
options_description_easy_init::
operator()(const char* name,
const value_semantic* s)
shared_ptr<const value_semantic> s)
{
shared_ptr<option_description> d(new option_description(name, s));
owner->add(d);
Expand All @@ -285,14 +286,31 @@ namespace boost { namespace program_options {
options_description_easy_init&
options_description_easy_init::
operator()(const char* name,
const value_semantic* s,
shared_ptr<const value_semantic> s,
const char* description)
{
shared_ptr<option_description> d(new option_description(name, s, description));

owner->add(d);
return *this;
}

options_description_easy_init&
options_description_easy_init::
operator()(const char* name,
const value_semantic* s)
{
return (*this)(name, shared_ptr<const value_semantic>(s));
}

options_description_easy_init&
options_description_easy_init::
operator()(const char* name,
const value_semantic* s,
const char* description)
{
return (*this)(name, shared_ptr<const value_semantic>(s), description);
}

const unsigned options_description::m_default_line_length = 80;

Expand Down
7 changes: 4 additions & 3 deletions src/value_semantic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/detail/convert.hpp>
#include <boost/program_options/detail/cmdline.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <set>

#include <cctype>
Expand Down Expand Up @@ -121,16 +122,16 @@ namespace boost { namespace program_options {
value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
}

BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool> >
bool_switch()
{
return bool_switch(0);
}

BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool> >
bool_switch(bool* v)
{
typed_value<bool>* r = new typed_value<bool>(v);
shared_ptr<typed_value<bool> > r = boost::make_shared<typed_value<bool> >(v);
r->default_value(0);
r->zero_tokens();

Expand Down
2 changes: 1 addition & 1 deletion test/cmdline_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void apply_syntax(options_description& desc,
stringstream ss;
ss << syntax;
while(ss >> s) {
value_semantic* v = 0;
boost::shared_ptr<value_semantic> v;

if (*(s.end()-1) == '=') {
v = value<string>();
Expand Down
Loading