Re: [Boost-bugs] [Boost C++ Libraries] #469: multitoken broken

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #469: multitoken broken
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2007-07-26 21:01:15


#469: multitoken broken
---------------------------+------------------------------------------------
  Reporter: rutavibaja | Owner: vladimir_prus
      Type: Bugs | Status: assigned
 Milestone: Boost 1.35.0 | Component: config
   Version: None | Severity: Problem
Resolution: None | Keywords:
---------------------------+------------------------------------------------
Comment (by anonymous):

 Given the following program_options description:

 {{{
 std::vector<std::string> multiItems;

 program_description desc;
 desc.add_options()
     ("multi", value<>(&multiItems)->multitoken(), "...");
 ....
 }}}

 Would we expect the command line: "myProgram --multi foo bar"
 to add two entries (foo and bar) into 'multiItems'?

 It currently (1.34) doesn't; bar gets lost. I can understand that this
 could be tricky, especially if positional options are also being used.

 If multitoken was never designed for this purpose, then currently the way
 to achieve the desired effect is to overload 'validate'. However, this is
 only necessary because of the use of 'lexical_cast' in the current
 validate implementations.

 To illustrate:

 {{{
 typedef std::pair<int int> PairOfInts;
 PairOfInts pairOfInts;

 program_description desc;
 desc.add_options()
     ("pair", value<>(&pairOfInts), "...");
 ....
 }}}

 With command line: "myProgram --pair 1 2":

 The current 'validate' code will stream (via lexical_cast) the string "1
 2" into lexical_stream, then stream it out to the value type, i.e. the
 std::pair.

 The problem there is that the stream-out of the string will only take the
 "1" part, so when it attempts to stream it back in, only one value is
 presented.

 If we had provided a stream operator for our pair:

 {{{
 std::istream& operator>>(std::istream &a_istr, PairOfInts &a_pair)
 {
     a_istr >> a_pair.first >> a_pair.second;
     return a_istr;
 }
 }}}

 Then an exception would fire trying to get the second value.

 The 'validate' code has a vector of strings, but only the first entry is
 filled.

 If the current (detail/value_semantic.hpp) validate code:

 {{{
 template<class T, class charT>
 void validate(boost::any& v,
               const std::vector< std::basic_string<charT> >& xs,
               T*, long)
 {
     validators::check_first_occurrence(v);
     std::basic_string<charT> s(validators::get_single_string(xs));
     try {
         v = any(lexical_cast<T>(s));
     }
     catch(const bad_lexical_cast&) {
         boost::throw_exception(invalid_option_value(s));
     }
 }
 }}}

 Was adjusted to not use lexical_cast, e.g.:

 {{{
 template<class T, class charT>
 void validate(boost::any& v,
               const std::vector< std::basic_string<charT> >& xs,
               T*, long)
 {
     validators::check_first_occurrence(v);
     std::basic_string<charT> s(validators::get_single_string(xs));
     std::istringstream istr(s);
     T value;
     if (!(istr >> value)
     {
         boost::throw_exception(invalid_option_value(s));
     }
     v = value;
 }
 }}}

 Then more complex types could be supported just by providing the stream-in
 operator, rather than overloaded 'validate's (that seem to have to go in
 namespace boost, too).

--
Ticket URL: <http://svn.boost.org/trac/boost/ticket/469#comment:3>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.


This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:56 UTC