c++boostboost-program-options

Boost program_options cannot parse uint8 vector argument


I am learning boost through examples, but I do not understand why the following c++ code failed to execute, I am only changing int to uint8_t, am I missing anything?

#include <stdint.h>
#include <iostream>
#include <vector>
#include <boost/program_options.hpp>

int main()
{
    namespace po = boost::program_options;

    const int argc = 5;
    const char* argv[] = {"foo", "--data", "1", "127", "255" };

    std::vector<uint8_t>  databytes;

    po::variables_map vm;
    po::options_description cmd_options( "options" );
    cmd_options.add_options()
        ( "data", po::value<std::vector<uint8_t>>( &databytes )->multitoken(), "DATA" );

    po::store( po::parse_command_line( argc, argv, cmd_options ), vm );
    po::notify( vm );

    std::cout << "size: " << databytes.size() << std::endl;
    for (size_t i = 0; i < databytes.size(); i++) {
        std::cout << i << ": " << (int)databytes[i] << std::endl;
    } 
}

Solution

  • I'd have my cake and eat it too. @StackOverflowNeko correctly points at a custom notifier. However, it conflicts a bit with using automatic variable notification. So if you avoid that, you can hide the conversion/validation step:

    Live On Coliru

    #include <boost/program_options.hpp>
    #include <iostream>
    #include <stdint.h>
    #include <vector>
    
    int main(int argc, char** argv) {
        namespace po = boost::program_options;
    
        // int const   argc   = 5;
        // char const* argv[] = {"foo", "--data", "1", "127", "255", nullptr};
    
        using Octet = uint8_t;
        std::vector<Octet> databytes;
    
        po::variables_map       vm;
        po::options_description cmd_options("options");
        cmd_options.add_options()(
            "data",
            po::value<std::vector<int>>()->multitoken()->notifier([&databytes](std::vector<int> const& raw) {
                for (auto el : raw) {
                    using L = std::numeric_limits<Octet>;
                    if (el < L::min() || el > L::max())
                        throw std::range_error("data:" + std::to_string(el));
                    databytes.push_back(static_cast<Octet>(el));
                }
            }),
            "DATA");
    
        po::store(po::parse_command_line(argc, argv, cmd_options), vm);
        po::notify(vm);
    
        std::cout << "size: " << databytes.size() << " [";
        for (auto sep = " "; int i : databytes)
            std::cout << std::exchange(sep, ", ") << i;
    
        std::cout << " ]\n";
    }
    

    With various test cases:

    + ./a.out
    size: 0 [ ]
    
    + ./a.out --data 1 127 255
    size: 3 [ 1, 127, 255 ]
    
    + ./a.out --data 1 2 3 256 4
    terminate called after throwing an instance of 'std::range_error'
      what():  data:256
    bash: line 10:  4254 Aborted                 (core dumped) ./a.out --data 1 2 3 256 4
    
    + ./a.out --data 1 2 3 -1 4
    terminate called after throwing an instance of 'boost::wrapexcept<boost::program_options::unknown_option>'
      what():  unrecognised option '-1'
    bash: line 11:  4257 Aborted                 (core dumped) ./a.out --data 1 2 3 -1 4
    
    + ./a.out --data 1 2 3 bogus 4
    terminate called after throwing an instance of 'boost::wrapexcept<boost::program_options::invalid_option_value>'
      what():  the argument ('bogus') for option '--data' is invalid
    bash: line 12:  4260 Aborted                 (core dumped) ./a.out --data 1 2 3 bogus 4
    
    + ./a.out --data=0 --data=1 --data=2 --data=3 --data=4 --data=5 --data=6 --data=7 --data=8 --data=9 --data=10 --data=11 --data=12 --data=13 --data=14 --data=15 --data=16 --data=17 --data=18 --data=19 --data=20 --data=21 --data=22 --data=23 --data=24 --data=25 --data=26 --data=27 --data=28 --data=29 --data=30 --data=31 --data=32 --data=33 --data=34 --data=35 --data=36 --data=37 --data=38 --data=39 --data=40 --data=41 --data=42 --data=43 --data=44 --data=45 --data=46 --data=47 --data=48 --data=49 --data=50 --data=51 --data=52 --data=53 --data=54 --data=55 --data=56 --data=57 --data=58 --data=59 --data=60 --data=61 --data=62 --data=63 --data=64 --data=65 --data=66 --data=67 --data=68 --data=69 --data=70 --data=71 --data=72 --data=73 --data=74 --data=75 --data=76 --data=77 --data=78 --data=79 --data=80 --data=81 --data=82 --data=83 --data=84 --data=85 --data=86 --data=87 --data=88 --data=89 --data=90 --data=91 --data=92 --data=93 --data=94 --data=95 --data=96 --data=97 --data=98 --data=99 --data=100 --data=101 --data=102 --data=103 --data=104 --data=105 --data=106 --data=107 --data=108 --data=109 --data=110 --data=111 --data=112 --data=113 --data=114 --data=115 --data=116 --data=117 --data=118 --data=119 --data=120 --data=121 --data=122 --data=123 --data=124 --data=125 --data=126 --data=127 --data=128 --data=129 --data=130 --data=131 --data=132 --data=133 --data=134 --data=135 --data=136 --data=137 --data=138 --data=139 --data=140 --data=141 --data=142 --data=143 --data=144 --data=145 --data=146 --data=147 --data=148 --data=149 --data=150 --data=151 --data=152 --data=153 --data=154 --data=155 --data=156 --data=157 --data=158 --data=159 --data=160 --data=161 --data=162 --data=163 --data=164 --data=165 --data=166 --data=167 --data=168 --data=169 --data=170 --data=171 --data=172 --data=173 --data=174 --data=175 --data=176 --data=177 --data=178 --data=179 --data=180 --data=181 --data=182 --data=183 --data=184 --data=185 --data=186 --data=187 --data=188 --data=189 --data=190 --data=191 --data=192 --data=193 --data=194 --data=195 --data=196 --data=197 --data=198 --data=199 --data=200 --data=201 --data=202 --data=203 --data=204 --data=205 --data=206 --data=207 --data=208 --data=209 --data=210 --data=211 --data=212 --data=213 --data=214 --data=215 --data=216 --data=217 --data=218 --data=219 --data=220 --data=221 --data=222 --data=223 --data=224 --data=225 --data=226 --data=227 --data=228 --data=229 --data=230 --data=231 --data=232 --data=233 --data=234 --data=235 --data=236 --data=237 --data=238 --data=239 --data=240 --data=241 --data=242 --data=243 --data=244 --data=245 --data=246 --data=247 --data=248 --data=249 --data=250 --data=251 --data=252 --data=253 --data=254 --data=255
    size: 256 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 ]