Skip to content

Commit 0565d1e

Browse files
committed
Merge from develop for 1.65.0
- Make options with implicit value use next token, like it did before. - Support boost::optional option variables. - Fix syntax error with BOOST_NO_EXCEPTIONS - Fix uninitlized position_key in some cases.
2 parents abbb5c1 + b35e654 commit 0565d1e

13 files changed

Lines changed: 163 additions & 66 deletions

File tree

build/Jamfile.v2

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,8 @@ SOURCES =
99
convert winmain split
1010
;
1111

12-
lib boost_program_options
12+
boost-lib program_options
1313
: $(SOURCES).cpp
14-
: <link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1 # tell source we're building dll's
15-
# See https://svn.boost.org/trac/boost/ticket/5049
14+
: # See https://svn.boost.org/trac/boost/ticket/5049
1615
<target-os>hpux,<toolset>gcc:<define>_INCLUDE_STDC__SOURCE_199901
17-
:
18-
: <link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
19-
;
20-
21-
boost-install boost_program_options ;
16+
;

doc/howto.xml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,58 @@ vector&lt;string&gt; to_pass_further = collect_unrecognized(parsed.options, incl
435435

436436
</section>
437437

438+
<section>
439+
<title>Testing Option Presence</title>
440+
441+
<para>Until now we have tested whether an option has been set using the
442+
<methodname alt="boost::program_options::variables_map::count">count</methodname> method on the &variables_map;
443+
class; as you are repeating the (string literal) name of the option this is prone to typos and/or errors
444+
resulting from renaming the option in one place but not the other:
445+
<programlisting><![CDATA[
446+
po::options_description desc("Allowed options");
447+
desc.add_options()
448+
("compression", po::value<int>(), "set compression level")
449+
;
450+
451+
po::variables_map vm;
452+
po::store(po::parse_command_line(ac, av, desc), vm);
453+
po::notify(vm);
454+
455+
if (vm.count("compression")) {
456+
cout << "Compression level was set to "
457+
<< vm["compression"].as<int>() << ".\n";
458+
} else {
459+
cout << "Compression level was not set.\n";
460+
}
461+
]]>
462+
</programlisting>
463+
</para>
464+
465+
<para>Instead, you can use a variable of type <classname alt="boost::optional">boost::optional</classname>;
466+
<libraryname>Program_options</libraryname> provides special support for <libraryname>Boost.Optional</libraryname>
467+
such that if the user specifies the option the <classname alt="boost::optional">boost::optional</classname>
468+
variable will be initialized to the appropriate value:
469+
<programlisting><![CDATA[
470+
po::options_description desc("Allowed options");
471+
boost::optional<int> compression;
472+
desc.add_options()
473+
("compression", po::value(&compression), "set compression level")
474+
;
475+
476+
po::variables_map vm;
477+
po::store(po::parse_command_line(ac, av, desc), vm);
478+
po::notify(vm);
479+
480+
if (compression)) {
481+
cout << "Compression level was set to " << *compression << ".\n";
482+
} else {
483+
cout << "Compression level was not set.\n";
484+
}
485+
]]>
486+
</programlisting>
487+
</para>
488+
</section>
489+
438490
</section>
439491

440492
<!--

doc/post_review_plan.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,4 @@
178178

179179
12. Deferred
180180

181-
- storing value to boost::optional
182181
- setting a flag when option is found

include/boost/program_options/detail/value_semantic.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#include <boost/throw_exception.hpp>
1010

11+
// forward declaration
12+
namespace boost { template<class T> class optional; }
13+
1114
namespace boost { namespace program_options {
1215

1316
extern BOOST_PROGRAM_OPTIONS_DECL std::string arg;
@@ -152,6 +155,20 @@ namespace boost { namespace program_options {
152155
}
153156
}
154157

158+
/** Validates optional arguments. */
159+
template<class T, class charT>
160+
void validate(boost::any& v,
161+
const std::vector<std::basic_string<charT> >& s,
162+
boost::optional<T>*,
163+
int)
164+
{
165+
validators::check_first_occurrence(v);
166+
validators::get_single_string(s);
167+
boost::any a;
168+
validate(a, s, (T*)0, 0);
169+
v = boost::any(boost::optional<T>(boost::any_cast<T>(a)));
170+
}
171+
155172
template<class T, class charT>
156173
void
157174
typed_value<T, charT>::

include/boost/program_options/eof_iterator.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ namespace boost {
6868

6969

7070
private: // iterator core operations
71-
friend class iterator_core_access;
71+
#ifdef __DCC__
72+
friend class boost::iterator_core_access;
73+
#else
74+
friend class iterator_core_access;
75+
#endif
7276

7377
void increment()
7478
{

include/boost/program_options/errors.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ namespace boost { namespace program_options {
169169
virtual void set_option_name(const std::string& option_name)
170170
{ set_substitute("option", option_name);}
171171

172-
std::string get_option_name() const throw()
172+
std::string get_option_name() const
173173
{ return get_canonical_option_name(); }
174174

175175
void set_original_token(const std::string& original_token)

include/boost/program_options/option.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace boost { namespace program_options {
3131
basic_option(const std::string& xstring_key,
3232
const std::vector< std::string> &xvalue)
3333
: string_key(xstring_key)
34+
, position_key(-1)
3435
, value(xvalue)
3536
, unregistered(false)
3637
, case_insensitive(false)

include/boost/program_options/value_semantic.hpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ namespace boost { namespace program_options {
3838
should be present on the command line. */
3939
virtual unsigned max_tokens() const = 0;
4040

41-
/** Returns true if the option should only take adjacent token,
42-
not one from further command-line arguments.
43-
*/
44-
virtual bool adjacent_tokens_only() const = 0;
45-
4641
/** Returns true if values from different sources should be composed.
4742
Otherwise, value from the first source is used and values from
4843
other sources are discarded.
@@ -53,7 +48,7 @@ namespace boost { namespace program_options {
5348
5449
*/
5550
virtual bool is_required() const = 0;
56-
51+
5752
/** Parses a group of tokens that specify a value of option.
5853
Stores the result in 'value_store', using whatever representation
5954
is desired. May be be called several times if value of the same
@@ -139,7 +134,6 @@ namespace boost { namespace program_options {
139134

140135
unsigned min_tokens() const;
141136
unsigned max_tokens() const;
142-
bool adjacent_tokens_only() const { return false; }
143137

144138
bool is_composing() const { return false; }
145139

@@ -224,10 +218,7 @@ namespace boost { namespace program_options {
224218

225219
/** Specifies an implicit value, which will be used
226220
if the option is given, but without an adjacent value.
227-
Using this implies that an explicit value is optional, but if
228-
given, must be strictly adjacent to the option, i.e.: '-ovalue'
229-
or '--option=value'. Giving '-o' or '--option' will cause the
230-
implicit value to be applied.
221+
Using this implies that an explicit value is optional,
231222
*/
232223
typed_value* implicit_value(const T &v)
233224
{
@@ -331,8 +322,6 @@ namespace boost { namespace program_options {
331322
}
332323
}
333324

334-
bool adjacent_tokens_only() const { return !m_implicit_value.empty(); }
335-
336325
bool is_required() const { return m_required; }
337326

338327
/** Creates an instance of the 'validator' class and calls

src/cmdline.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,6 @@ namespace boost { namespace program_options { namespace detail {
313313
if (!xd)
314314
continue;
315315

316-
if (xd->semantic()->adjacent_tokens_only())
317-
continue;
318-
319316
unsigned min_tokens = xd->semantic()->min_tokens();
320317
unsigned max_tokens = xd->semantic()->max_tokens();
321318
if (min_tokens < max_tokens && opt.value.size() < max_tokens)
@@ -437,9 +434,6 @@ namespace boost { namespace program_options { namespace detail {
437434
// (the value in --foo=1) counts as a separate token, and if present
438435
// must be consumed. The following tokens on the command line may be
439436
// left unconsumed.
440-
441-
// We don't check if those tokens look like option, or not!
442-
443437
unsigned min_tokens = d.semantic()->min_tokens();
444438
unsigned max_tokens = d.semantic()->max_tokens();
445439

@@ -453,9 +447,8 @@ namespace boost { namespace program_options { namespace detail {
453447
invalid_command_line_syntax(invalid_command_line_syntax::extra_parameter));
454448
}
455449

456-
// If an option wants, at minimum, N tokens, we grab them there,
457-
// when adding these tokens as values to current option we check
458-
// if they look like options
450+
// Grab min_tokens values from other_tokens, but only if those tokens
451+
// are not recognized as options themselves.
459452
if (opt.value.size() <= min_tokens)
460453
{
461454
min_tokens -= static_cast<unsigned>(opt.value.size());
@@ -465,7 +458,7 @@ namespace boost { namespace program_options { namespace detail {
465458
min_tokens = 0;
466459
}
467460

468-
// Everything's OK, move the values to the result.
461+
// Everything's OK, move the values to the result.
469462
for(;!other_tokens.empty() && min_tokens--; )
470463
{
471464
// check if extra parameter looks like a known option

src/variables_map.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,15 @@ namespace boost { namespace program_options {
4242
string option_name;
4343
string original_token;
4444

45+
#ifndef BOOST_NO_EXCEPTIONS
4546
try
47+
#endif
4648
{
4749

4850
// First, convert/store all given options
4951
for (i = 0; i < options.options.size(); ++i) {
5052

5153
option_name = options.options[i].string_key;
52-
original_token = options.options[i].original_tokens.size() ?
53-
options.options[i].original_tokens[0] :
54-
option_name;
5554
// Skip positional options without name
5655
if (option_name.empty())
5756
continue;
@@ -68,7 +67,7 @@ namespace boost { namespace program_options {
6867
if (xm.m_final.count(option_name))
6968
continue;
7069

71-
string original_token = options.options[i].original_tokens.size() ?
70+
original_token = options.options[i].original_tokens.size() ?
7271
options.options[i].original_tokens[0] : "";
7372
const option_description& d = desc.find(option_name, false,
7473
false, false);

0 commit comments

Comments
 (0)