Re: [Boost-bugs] [Boost C++ Libraries] #12535: boost::program_options cannot handle std::uint8_t arguments

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #12535: boost::program_options cannot handle std::uint8_t arguments
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2017-07-08 11:59:41


#12535: boost::program_options cannot handle std::uint8_t arguments
-------------------------------+-----------------------------
  Reporter: gilgamash | Owner: Vladimir Prus
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: program_options
   Version: Boost 1.61.0 | Severity: Problem
Resolution: | Keywords: uint8_t
-------------------------------+-----------------------------

Comment (by Kalle Olavi Niemitalo <kon@…>):

 == Compile with:

 c++ -std=c++11 -Wall -Wextra -Wold-style-cast -pedantic -ggdb
 program_options_uint8_demo.cc -lboost_program_options -o
 program_options_uint8_demo

 == Run with:

 ./program_options_uint8_demo

 == Actual result:

 {{{
 terminate called after throwing an instance of
 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::program_options::invalid_option_value>
>'
   what(): the argument ('241') for option '--num' is invalid
 }}}

 == Backtrace when the exception is being thrown:

 0. in !__cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 1. in boost::throw_exception<boost::bad_lexical_cast> (e=...) at
 /usr/include/boost/throw_exception.hpp:70
 2. in boost::detail::lexical_cast_do_cast<unsigned char,
 std::string>::lexical_cast_impl (arg="241") at
 /usr/include/boost/lexical_cast.hpp:2375
 3. in boost::lexical_cast<unsigned char, std::string> (arg="241") at
 /usr/include/boost/lexical_cast.hpp:2543
 4. in boost::program_options::validate<unsigned char, char> (v=...,
 xs=std::vector of length 1, capacity 1 = {...}) at
 /usr/include/boost/program_options/detail/value_semantic.hpp:89
 5. in boost::program_options::typed_value<unsigned char, char>::xparse
 (this=0x619070, value_store=..., new_tokens=std::vector of length 1,
 capacity 1 = {...}) at
 /usr/include/boost/program_options/detail/value_semantic.hpp:170
 6. in
 boost::program_options::value_semantic_codecvt_helper<char>::parse(boost::any&,
 std::vector<std::string, std::allocator<std::string> > const&, bool) const
 () from /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.55.0
 7. in
 boost::program_options::store(boost::program_options::basic_parsed_options<char>
 const&, boost::program_options::variables_map&, bool) () from
 /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.55.0
 8. in main () at program_options_uint8_demo.cc:16

 == Cause:

 lexical_cast sees uint8_t as unsigned char and expects a one-character
 string, but "241" has three characters. Likewise, --num=9 would set
 num='9', i.e. num=57 in ASCII, not num=9.

 == Rationale:

 I expect value<char> to parse a one-character argument; if that were
 changed to parse an integer, it would be too surprising.

 OTOH, options that require a one-character argument and save that as char
 don't seem very useful nowadays, because of multibyte characters.

 If value<char> parses a one-character argument, and int8_t is defined as
 char (rather than signed char), then value<int8_t> is undistinguishable
 from value<char> and must likewise parse a one-character argument.

 If value<char> parsed a one-character argument but value<unsigned char>
 were changed to parse an integer, that would be an annoying asymmetry.

 Passing arbitrary raw bytes as unsigned char in the command line is not
 feasible because argv[] does not support null bytes and Windows always
 requires a conversion from UTF-16.

 == Recommendation for programs:

 Define the argument type as a string if you want a single character, and
 as int if you want an 8-bit integer. Then separately check that the
 string isn't too long or that the integer isn't out of range.

 == Recommendation for Boost:

 Keep value<char> and value<unsigned char> parsing a single-character
 argument like now, but change the error message to say that the argument
 is too long and a single character was expected. This will make it easier
 for the programmer to understand how to fix the problem if integer parsing
 was intended.

 Perhaps add separate integer_value functions that support uint8_t and
 allow the programmer to specify the permitted range of integers.

-- 
Ticket URL: <https://svn.boost.org/trac10/boost/ticket/12535#comment:2>
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-07-08 12:04:04 UTC