An alternative to getopt() and getopt_long() (and boost::program_options) by using of callback functions for each recognized option in the shape of:
- classical function-pointers
- anonymous "lambda" functions
- or virtual object-functions
- Avoiding of global variables like "optind" or "optarg".
- Using of a callback function for each option instead of (confusing huge) switch-case- or if-statements. (Avoiding of spaghetti-code.)
- Use of anonymous callback functions (lambda functions) possible. That means implementation of the function body directly in the option-list initializer possible. (See code-example below.)
- Object oriented flavor: Short option-name (if given), long option-name (if given) and help-text (if given) are bound together in a single object by a corresponding callback function.
- Avoiding of redundance: If you'll change a option name, so you have to do this on one place in your source-code only.
- Commands by mixed order of options and non-options are possible.
- Specialized callback objects per single option and/or initializer-lists with callback lambda- functions and/or function-pointers are possible. (This is a matter of taste.)
- Scalable, if a serten kind of option-type won't used for your project just define the corresponding compiler-switch (CONFIG_CLOP_NO_...) in your Makefile respectively build-system to reduce memory, provided you'll link the source-code directly to your project rather than the shared-library.
If you intend to write a pure C-project or you are not allowed to write your program in C++ (not to mention in C++11), so you can take a look in the following link:
https://github.com/UlrichBecker/command_line_option_parser
A practical application using this module you can find in this repository: https://github.com/UlrichBecker/DocFsm
Excuses my Eric Allman coding-style and my bad English ;-)
Example for using lambda callback function in a initializer-list:
See also ./example/lambda/cmd_opt_lambda.cpp
#include <parse_opts.hpp> using namespace std; using namespace CLOP; // Namespace for Command-Line-Option-Parser int main( int argc, char** ppArgv ) { // Initializer-list vector<OPTION> optList = { { OPT_LAMBDA( parser, { cout << "Usage: " << parser->getProgramName() << " [options,...]\n"; parser->list( cout ); cout << endl; exit( EXIT_SUCCESS ); return 0; }), .m_hasArg = OPTION::NO_ARG, .m_id = 0, .m_shortOpt = 'h', .m_longOpt = "help", .m_helpText = "Print this help and exit" }, { //... further options ... } }; PARSER parser( argc, ppArgv, optList ); for( int i = 1; i < argc; i++ ) { i = parser( i ); if( i < 0 ) return EXIT_FAILURE; if( i < argc ) cout << "Non option argument on index " << i << ": " << ppArgv[i] << endl; } // Do something others... return EXIT_SUCCESS; }Example for using virtual object-functions for each option:
See also ./example/objects/cmd_opt_objects.cpp
#include <parse_opts.hpp> using namespace std; using namespace CLOP; // Namespace for Command-Line-Option-Parser class OPTION_HELP: public OPTION_V { public: OPTION_HELP( void ) { m_hasArg = NO_ARG; m_shortOpt = 'h'; m_longOpt = "help"; m_helpText = "Print this help and exit."; } private: // Function becomes immediately triggered if the parser recognized // the option "-h" or "--help" in the commend-line. int onGiven( PARSER* poParser ) override { cout << "Usage: " << poParser->getProgramName() << " [options,...]\n"; poParser->list( cout ); cout << endl; exit( EXIT_SUCCESS ); return 0; } }; // Further classes inherited of the base-class CLOP::OPTION_V ... class MY_PARSER: public PARSER { public: MY_PARSER( int argc, char** ppArgv ): PARSER( argc, ppArgv ) {} // The overwriting of the following callback-function makes it enable // to evaluate non-option arguments too. int onArgument( void ) override { cout << "Non option argument on index " << getArgIndex() << ": " << getArgVect()[getArgIndex()] << endl; return 1; // Continue parsing for mixed order. } }; int main( int argc, char** ppArgv ) { MY_PARSER parser( argc, ppArgv ); OPTION_HELP optHelp; // ... further objects of the base CLOP::OPTION_V if( parser( optHelp )() < 0 ) return EXIT_FAILURE; // Do something others ... return EXIT_SUCCESS; }