CLI11
CLI11 copied to clipboard
One option without adding any
Pulled CLI11 yesterday and today. Starting a small app
int main(int argc, char **argv)
{
std::cout<<"main "<<std::endl;
CLI::App app{"QMechanic"};
app.parse(argc, argv);
std::cout << "app.parsed:" << std::endl;
std::cout<<"get_options size "<<app.get_options().size()<<std::endl;
return EXIT_SUCCESS;
}
running ./main results in
get_options size 1
There is already one option? If code is added to iterator over
for(std::vector< CLI::Option*>::const_iterator it=app.get_options().cbegin();it!=app.get_options().cend();++it){
std::cout<<"Option ";
std::cout<<std::endl;
}
the iteration happens once and see the "Option ".
If count(or other members such as has_description()) is checked a crash happens
for(std::vector< CLI::Option*>::const_iterator it=app.get_options().cbegin();it!=app.get_options().cend();++it){
if((*it)->count()>0){
std::cout<<"Option ";
std::cout<<std::endl;
}
}
If one option is coded the number of options is 2 and the crashes still happen. If a counter is added to skip the first option returned by the const_iterator then no crash and have access to members such as has_description and get_description.
Iterating with it++ instead of ++it yields different behavior but still crashes.
Oh compile lines are:
g++ -fPIE -std=c++17 -I../working-copyDevCLI11/CLI11/include -Wl,--allow-multiple-definition -MT main.o -MMD -MP -O3 -c -o main.o main.cpp
g++ -pie -Wl,--allow-multiple-definition -o main main.o -lm -lpthread -lz -lstdc++ -ldl -lrt
Quick comment; that's the wrong way to run the parse. It should be:
try {
app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
return app.exit(e);
}
(or use the CLI11_PARSE macro). If there's an error, that will exit nicely.
The one option is -h/--help. You can remove it, but it's there by default.
You are not iterating over correctly - ~~you are dereferencing twice~~, you are calling get_options() twice and comparing, which is the crash. Here's a working example:
// This file is a "Hello, world!" CLI11 program
#include "CLI11.hpp"
#include <iostream>
#include <string>
int main(int argc, char **argv)
{
std::cout<<"main "<<std::endl;
CLI::App app{"QMechanic"};
CLI11_PARSE(app, argc, argv); // Nicer, but worked the old way as long as no error was thrown
std::cout << "app.parsed:" << std::endl;
std::cout << "get_options size " << app.get_options().size() << std::endl;
for(const auto&& it : app.get_options()){
std::cout << it->get_name() << " " << std::endl;
if(it->count() > 0){
std::cout << "Option ";
std::cout << std::endl;
}
}
return EXIT_SUCCESS;
}
@henryiii they are not "dereferencing twice" - they just iterate the old style - with an iterator that itself needs to be dereferenced.
I think you're referring to a fact, that App::get_options() returns vector by value, so they are comparing iterators from many different vectors, and nothing good can come out of that.
Ahh, yes, you call get_options twice, so the begin and end are incorrect. I would recommend using C++11 style iteration if you are in C++17, not C++98. The copy is made because that's not actually how the data is stored, they are actually a vector of unique pointers.