Coder Social home page Coder Social logo

fytch / programoptions.hxx Goto Github PK

View Code? Open in Web Editor NEW
133.0 14.0 13.0 520 KB

Single-header program options parsing library for C++11

License: MIT License

CMake 1.86% C++ 98.14%
cpp cpp11 header-only option-parser argument-parser command-line-parser

programoptions.hxx's Introduction

ProgramOptions.hxx

Build Status Build Status GitHub License

Contents

Getting started

The quickest way to get started is to download ProgramOptions.hxx as well as one of the samples and go from there.

sample.cxx

The default choice. Incorrect usage of ProgramOptions.hxx's API will trigger an assertion which will crash the program in debug mode.

sample_exceptions.cxx

In this sample, we #define PROGRAMOPTIONS_EXCEPTIONS. In consequence, incorrect usage of ProgramOptions.hxx's API will throw an exception both in debug and release mode.

Design goals

  • Non-intrusive. ProgramOptions.hxx requires neither additional library binaries nor integration into the build process. Just drop in the header, include it and you're all set. ProgramOptions.hxx doesn't force you to enable exceptions or RTTI and runs just fine with -fno-rtti -fno-exceptions.
  • Intuitive. ProgramOptions.hxx is designed to feel smooth and blend in well with other modern C++11 code.
  • Correct. Extensive unit tests and runtime checks contribute to more correct software, both on the side of the user and the developer of ProgramOptions.hxx.
  • Permissive. The MIT License under which ProgramOptions.hxx is published grants unrestricted freedom.

Features

Screenshot

Syntax

ProgramOptions.hxx adheres to the following rules:

  • Short options (-g) consist of a single hyphen and an identifying character. The character must be graphic (isgraph).
    • To pass an argument to the option, these syntaxes are allowed: -O3, -O=3, -O 3
    • Multiple short options may be grouped; -alt is equal to -a -l -t. This is only allowed if all options (including the last) don't require an argument.
  • Long options (--version) consist of two leading hyphens followed by an identifier. The identifier may consist of alphanumeric (isalnum) characters, hyphens, and underscores but must not start with a hyphen.1
    • To pass an argument to the option, these syntaxes are allowed: --optimization=3, --optimization 3
  • Non-option arguments (file.txt), also referred to as operands in POSIX lingo or positional arguments, are everything except options and options' arguments.
  • Short options, long options and non-option arguments can be interleaved at will. Their relative position is retained, i.e. ProgramOptions.hxx does not reorder them.
  • A single hyphen - is parsed as a non-option argument.
  • Two hyphens -- terminate the option input. Any following arguments are treated as non-option arguments, even if they begin with a hyphen.

1 Note that -version (with only a single hyphen) would be interpreted as the option -v with the argument ersion.

Integration

ProgramOptions.hxx is very easy to integrate. After downloading the header file from the include folder and putting it into your project folder, all it takes is a simple:

#include "ProgramOptions.hxx"

Don't forget to compile with C++11 enabled, i.e. with -std=c++11.

git

If you want to integrate ProgramOptions.hxx into your project that uses git, you can write:

git submodule add https://github.com/Fytch/ProgramOptions.hxx third_party/ProgramOptions.hxx

You may replace third_party/ProgramOptions.hxx by any path.

CMake

If you want to integrate ProgramOptions.hxx into your project that uses CMake, add the following to your CMakeLists.txt:

add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/third_party/ProgramOptions.hxx")
target_link_libraries(YourExecutable ProgramOptionsHxx)

You must replace /third_party/ProgramOptions.hxx by the correct path and YourExecutable by the targets that use ProgramOptions.hxx.

You can then include the header by writing:

#include <ProgramOptions.hxx>

TL;DR

Copy and paste this and start hacking:

#include <ProgramOptions.hxx>
#include <iostream>
#include <vector>
#include <string>

int main(int argc, char** argv) {
    po::parser parser;

    std::uint32_t opt = 0;
    parser["optimization"]
        .abbreviation('O')
        .description("set the optimization level")
        .bind(opt);

    auto& help = parser["help"]
        .abbreviation('?')
        .description("print this help screen");

    std::vector<std::string> files;
    parser[""]
        .bind(files);

    if(!parser(argc, argv))
        return -1;

    if(help.was_set()) {
        std::cout << parser << '\n';
        return 0;
    }

    std::cout << "compiling " << files.size() << " files with O" << opt << '\n';
}

Usage

Using ProgramOptions.hxx is straightforward; we'll explain it by means of practical examples. All examples shown here and more can be found in the /examples directory, all of which are well-documented.

Example 1 (abbreviation, u32, available, get)

The following snippet is the complete source code of a simple program expecting an integer optimization level.

#include <ProgramOptions.hxx>
#include <iostream>

int main(int argc, char** argv) {
    po::parser parser;
    auto& O = parser["optimization"]  // corresponds to --optimization
        .abbreviation('O')            // corresponds to -O
        .type(po::u32);               // expects an unsigned 32-bit integer

    parser(argc, argv);               // parses the command line arguments

    if(!O.available())
        std::cout << "no optimization level set!\n";
    else
        std::cout << "optimization level set to " << O.get().u32 << '\n';
}

And in action:

$ ./optimization
no optimization level set!
$ ./optimization -O2
optimization level set to 2
$ ./optimization -O=0xFF
optimization level set to 255
$ ./optimization -O3 --optimization 1e2
optimization level set to 100

Example 2 (fallback, was_set, string, multi)

Let's expand on the previous code. We want it to assume a certain value for the option optimization even if the user sets none. This can be achieved through the .fallback(...) method. After parsing, the method .was_set() tells us whether the option was actually set by the user or fell back on the default value.

Furthermore, we want to implement the option -I to let the user specify include paths. Paths should not be converted to any arithmetic type so we simply set the type to po::string.

By calling the method .multi() we're telling the library to store all values, not just the last one. The number of arguments can be retrieved by calling the .size() or the .count() method. The individual values may be read by means of the iterators returned by .begin() and .end(). Bear in mind that these iterators point to instances of po::values so you still need to refer to the correct member, in this case .string. One way of avoiding this is to use the iterators returned by .begin<po::string>() and .end<po::string>() instead. These random-access iterators behave as if they pointed to instances of std::strings. For more information, refer to Example 4.

#include <ProgramOptions.hxx>
#include <iostream>

int main(int argc, char** argv) {
    po::parser parser;
    auto& O = parser["optimization"]  // corresponds to --optimization
        .abbreviation('O')            // corresponds to -O
        .type(po::u32)                // expects an unsigned 32-bit integer
        .fallback(0);                 // if --optimization is not explicitly specified, assume 0

    auto& I = parser["include-path"]  // corresponds to --include-path
        .abbreviation('I')            // corresponds to -I
        .type(po::string)             // expects a string
        .multi();                     // allows multiple arguments for the same option

    parser(argc, argv);               // parses the command line arguments

    // .was_set() reports whether the option was specified by the user or relied on the predefined fallback value.
    std::cout << "optimization level (" << (O.was_set() ? "manual" : "auto") << ") = " << O.get().u32 << '\n';

    // .size() and .count() return the number of given arguments. Without .multi(), their return value is always <= 1.
    std::cout << "include paths (" << I.size() << "):\n";

    // Here, the non-template .begin() / .end() methods were used. Their value type is po::value,
    // which is not a value in itself but contains the desired values as members, i.e. i.string.
    for(auto&& i : I)
        std::cout << '\t' << i.string << '\n';
}

In action:

$ ./include -I/usr/include/foo -I "/usr/include/bar" -O3
optimization level (manual) = 3
include paths (2):
        /usr/include/foo
        /usr/include/bar

Example 3 (description, callback, unnamed parameter)

Up until now, we were missing the infamous --help command. While ProgramOptions.hxx will take over the tedious work of neatly formatting and displaying the options, it doesn't add a --help command automatically. That's up to us and so is adding an apt description for every available option. We may do so by use of the .description(...) method.

But how do we accomplish printing the options whenever there's a --help command? This is where callbacks come into play. Callbacks are functions that we supply to ProgramOptions.hxx to call. After we handed them over, we don't need to worry about invoking them as that's entirely ProgramOptions.hxx' job. In the code below, we pass a lambda whose sole purpose is to print the options. Whenever the corresponding option occurs (--help in this case), the callback is invoked.

The unnamed parameter "" is used to process non-option arguments. Consider the command line: gcc -O2 a.c b.c Here, unlike -O2, a.c and b.c do not belong to an option and neither do they start with a hyphen. They are non-option arguments. In ProgramOptions.hxx, you treat the unnamed parameter like any other option. Options and the unnamed parameter only differ in their default settings.

Note that, in order to pass arguments starting with a hyphen to the unnamed parameter, you'll have to pass -- first, signifying that all further arguments are non-option arguments and that they should be passed right to the unnamed parameter without attempting to interpret them.

#include <ProgramOptions.hxx>
#include <iostream>

int main(int argc, char** argv) {
    po::parser parser;
    auto& O = parser["optimization"]
        .abbreviation('O')
        .description("set the optimization level (default: -O0)")
        .type(po::u32)
        .fallback(0);

    auto& I = parser["include-path"]
        .abbreviation('I')
        .description("add an include path")
        .type(po::string)
        .multi();

    auto& help = parser["help"]
        .abbreviation('?')
        .description("print this help screen")
        // .type(po::void_)   // redundant; default for named parameters
        // .single()          // redundant; default for named parameters
        .callback([&]{ std::cout << parser << '\n'; });
                              // callbacks get invoked when the option occurs

    auto& files = parser[""]  // the unnamed parameter is used for non-option arguments as in: gcc a.c b.c
        // .type(po::string)  // redundant; default for the unnamed parameter
        // .multi()           // redundant; default for the unnamed parameter
        .callback([&](std::string const& x){ std::cout << "processed \'" << x << "\' successfully!\n"; });
                              // as .get_type() == po::string, the callback may take an std::string

    // parsing returns false if at least one error has occurred
    if(!parser(argc, argv)) {
        std::cerr << "errors occurred; aborting\n";
        return -1;
    }
    // we don't want to print anything else if the help screen has been displayed
    if(help.was_set())
        return 0;

    std::cout << "processed files: " << files.size() << '\n';

    // .was_set() reports whether the option was specified by the user or relied on the predefined fallback value.
    std::cout << "optimization level (" << (O.was_set() ? "manual" : "auto") << ") = " << O.get().u32 << '\n';

    // .size() and .count() return the number of given arguments. Without .multi(), their return value is always <= 1.
    std::cout << "include paths (" << I.size() << "):\n";

    // Here, the non-template .begin() / .end() methods were used. Their value type is
    // po::value, which is not a value in itself but contains the desired values as members, i.e. i.string.
    for(auto&& i : I)
        std::cout << '\t' << i.string << '\n';
}

How the help screen appears:

$ ./files --help
Usage:
  files.exe [arguments...] [options]
Available options:
  -O, --optimization  set the optimization level (default: -O0)
  -I, --include-path  add an include path
  -?, --help          print this help screen

In action:

$ ./files -I ./include foo.cxx bar.cxx -O3 -- --qux.cxx
processed 'foo.cxx' successfully!
processed 'bar.cxx' successfully!
processed '--qux.cxx' successfully!
processed files: 3
optimization level (manual) = 3
include paths (1):
        ./include

Example 4 (more callbacks, more fallbacks, f64, to_vector)

In this example, we will employ already known mechanics but lay the focus on their versatility.

Let's start with callbacks:

  • Multiple callbacks are invoked in order of their addition.
  • For an option of type po::f64, the possible parameter types of a callback are: <none>, std::string, po::f64_t, or any type that is implicitly constructible from these.
  • When using C++14, auto and auto&& are also a valid callback parameter type.

About .fallback(...):

  • Fallbacks can be provided in any form that would also suffice when parsed, i.e. also as a std::string.
  • If .multi() is set, .fallback(...) can take an arbitrary number of values.

About .type(...):

  • po::void_: No value, the option has either occurred or not
  • po::string: Stores the unaltered string
  • po::i32 / po::i64: Signed integer; supports decimal, hexadecimal (0x), binary (0b) and positive exponents (e0)
  • po::u32 / po::u64: Unsigned integer; same as with signed integers
  • po::f32 / po::f64: Floating point value; supports exponents (e0), infinities (inf) and NaNs (nan)

Reading .multi() options:

  • .begin() and .end(): Random-access iterators that point to po::values; thus you have to choose the right member when dereferencing, e.g. .begin()->i32
  • .begin<po::i32>() and .end<po::i32>(): Random-access iterators that point to values of the specified type
  • .get(i) (and .size()): Reference to po::value; there's also a .get_or(i, v) method, returning the second parameter if the index is out of range
  • .to_vector<po::i32>(): Returns a std::vector with elements of the specified type
#include <ProgramOptions.hxx>
#include <iostream>
#include <numeric>

int main(int argc, char** argv) {
    po::parser parser;

    auto& x = parser[""]        // the unnamed parameter
        .type(po::f64)          // expects 64-bit floating point numbers
        .multi()                // allows multiple arguments
        .fallback(-8, "+.5e2")  // if no arguments were provided, assume these as default
        .callback([&]{ std::cout << "successfully parsed "; })
        .callback([&](std::string const& x){ std::cout << x; })
        .callback([&]{ std::cout << " which equals "; })
        .callback([&](po::f64_t x){ std::cout << x << '\n'; });

    parser(argc, argv);

    std::cout << "(+ ";
    for(auto&& i : x.to_vector<po::f64>())  // unnecessary copy; for demonstration purposes only
        std::cout << i << ' ';
    std::cout << ") = " << std::accumulate(x.begin<po::f64>(), x.end<po::f64>(), po::f64_t{}) << '\n';
}

In action:

$ ./sum
(+ -8 50) = 42
$ ./sum 39.5 2.5
successfully parsed 39.5 which equals 39.5
successfully parsed 2.5 which equals 2.5
(+ 39.5 2.5) = 42
$ ./sum 1e3 -1e0 -1e1 -2e2
successfully parsed 1e3 which equals 1000
successfully parsed -1e0 which equals -1
successfully parsed -1e1 which equals -10
successfully parsed -2e2 which equals -200
(+ 1000 -1 -10 -200) = 789
$ ./sum inf -1
successfully parsed inf which equals inf
successfully parsed -1 which equals -1
(+ inf -1) = inf
$ ./sum 12 NaN
successfully parsed 12 which equals 12
successfully parsed NaN which equals nan
(+ 12 nan) = nan

Example 5 (bind)

Until now, we defined the type, plurality and fallback value of each option manually by invoking .type, .single/.multi and .fallback. If we just want to extract the values from the parser and store them in a variable, .bind offers a more convenient and safer way of achieving this and ought to be preferred. .bind internally sets the type and the plurality (.single/.multi) of the corresponding option (but not the fallback).

We may bind options to variables of type std::string, to 32- or 64-bit signed integers, unsigned integer, floating point numbers or to STL containers consisting of elements of such type. If we want to use custom container types and/or custom insertion routines, we have to use .bind_container(container&, inserter) which accepts a binary function with the signature inserter(container_t&, container_t::value_type const&) (up to implicit conversion).

#include <ProgramOptions.hxx>
#include <cstdint>
#include <string>
#include <vector>
#include <deque>
#include <iostream>

int main(int argc, char** argv) {
    po::parser parser;

    std::uint32_t optimization = 0; // the value we set here acts as an implicit fallback
    parser["optimization"]
        .abbreviation('O')
        .description("set the optimization level (default: -O0)")
        .bind(optimization);        // write the parsed value to the variable 'optimization'
                                    // .bind(optimization) automatically calls .type(po::u32) and .single()

    std::vector<std::string> include_paths;
    parser["include-path"]
        .abbreviation('I')
        .description("add an include path")
        .bind(include_paths);       // append paths to the vector 'include_paths'

    auto& help = parser["help"]
        .abbreviation('?')
        .description("print this help screen");

    std::deque<std::string> files;
    parser[""]
        .bind(files);               // append paths to the deque 'include_paths

    if(!parser(argc, argv))
        return -1;

    // we don't want to print anything else if the help screen has been displayed
    if(help.was_set()) {
        std::cout << parser << '\n';
        return 0;
    }

    // print the parsed values
    // note that we don't need to access parser anymore; all data is stored in the bound variables
    std::cout << "optimization level = " << optimization << '\n';
    std::cout << "include files (" << files.size() << "):\n";
    for(auto&& i : files)
        std::cout << '\t' << i << '\n';
    std::cout << "include paths (" << include_paths.size() << "):\n";
    for(auto&& i : include_paths)
        std::cout << '\t' << i << '\n';
}

Miscellaneous functions

void po::parser::silent()

Suppresses all communication via stderr. Without this flag, ProgramOptions.hxx notifies the user in case of warnings or errors occurring while parsing. For instance, if an option requires an argument of type i32 and it couldn't be parsed, overflowed or wasn't provided at all, ProgramOptions.hxx would print an error saying that the option's argument is invalid and that it hence was ignored.

Defaults

This small table helps clarifying the defaults for the different kinds of options.

Name "long-option" "x" "" (unnamed parameter)
.abbreviation '\0' (none) 'x' (disallowed)
.type po::void_ po::void_ po::string
.single / .multi .single .single .multi

Flags

All flags have to be #defined before including ProgramOptions.hxx.

#define PROGRAMOPTIONS_EXCEPTIONS

When this flag is set, ProgramOptions.hxx's functions' preconditions are validated with exceptions instead of assertions. If a precondition isn't met, an std::logic_error is thrown whose explanatory strings starts with "ProgramOptions.hxx:N:" where N is the respective line number.

❗ This flag must not vary across different translation units of a single program in order to not violate C++' one definition rule (ODR).

#define NDEBUG

Setting this flag disables all assertions.

❗ This flag must not vary across different translation units of a single program in order to not violate C++' one definition rule (ODR).

#define PROGRAMOPTIONS_NO_COLORS

Setting this flag disables colored output. On Windows, ProgramOptions.hxx uses the WinAPI (i.e. SetConsoleTextAttribute) to achieve colored console output whereas it uses ANSI escape codes anywhere else.

❗ This flag must not vary across different translation units of a single program in order to not violate C++' one definition rule (ODR).

Third-party libraries

  • Catch for unit testing.

License

ProgramOptions.hxx is licensed under the MIT License. See the enclosed LICENSE.txt for more information.

programoptions.hxx's People

Contributors

deinfreund avatar fytch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

programoptions.hxx's Issues

iterate through all options

hi Josua
Good job on this library! It looks very nice and easy to use too! Thank you very much, it will save me time!
I have a quick question for you. I need to turn all program options into a JSON object. For that I would like to iterate through all option-name:value pairs. Is there any way to do this?
Thanks

Crash when printing help under Windows + MSYS2 mingw

When I try to print help for my test application in MSYS2 bash, it crashes:

Usage:
  websocketserver.exe [options]
Available options:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Assertion failed!

Program: D:\msys64\home\user\cpp\tools\websocketppExample\build\dist\bin\websocketserver.exe
File: ../external/ProgramOptions/src/ProgramOptions/ProgramOptions.hxx, Line 103

It works as it should in windows commandline.

Code to reproduce:

int main(int argc, char** argv)
{
    po::parser parser;
    parser["help"]
        .abbreviation('?')
        .description("print this help screen")
        .callback([&] { std::cout << parser << '\n'; });
    parser(argc, argv);
    if (parser["help"].size())
        return 0;
}

How I have "fixed" it (ProgramOptions.hxx: line ~104):

#ifdef PROGRAMOPTIONS_WINDOWS
			m_stream << std::flush;
			m_console = GetStdHandle( STD_OUTPUT_HANDLE );
			assert( m_console != INVALID_HANDLE_VALUE );
			CONSOLE_SCREEN_BUFFER_INFO info;
			const bool result = GetConsoleScreenBufferInfo( m_console, &info );
			//assert( result ); //<<<<< COMMENT THIS LINE :)
			( void )result;
			m_old_attributes = info.wAttributes;
			WORD attribute = 0;
			if( color < 0 ) {

After that, it works as it should. Is the check for result from GetCOnsoleScreenBufferInpfo necessary?

exceptions

hi

I defined
#define PROGRAMOPTIONS_SILENT

and I expected to get exceptions instead of the error messages, but there were no exceptions even when I had non-option arguments. Also, I'm not sure this really needs to be a pre-processor definition. Could you not have a .verbose() member to enable std::cerr messages as well as .throw_on_error(bool) to enable/disable exceptions on error? I think by default it should throw an exception unless user sets throw_on_error(false);
I definitely think that a non-option argument should result in an exception, because the app user is clearly trying to do something, and if the app can't do it, it should not ignore it. That's confusing.

I would also like to get easier access to non-option arguments, other than just via a callback. Could you not simply add a function like:

std::vector<std::string> non_option_args(void);

That way I can easily do what I want with them without callbacks.

Thanks, peter

Warnings

A few undesirable warnings firing. Easy enough to fixup.

ProgramOptions.h(1684): warning C4244: '=': conversion from 'int' to 'char', possible loss of data
ProgramOptions.h(1686): warning C4244: '=': conversion from 'int' to 'char', possible loss of data
ProgramOptions.h(2037): warning C4456: declaration of 'i' hides previous local declaration
ProgramOptions.h(644): warning C4456: declaration of 'neg' hides previous local declaration

binding variables

hi
Here is another idea. How about being able to 'bind' an option to a variable. This would work expecially well for 'mandatory' options. That way, the value would be set directly in a corresponding variable. Like:

double some_num;
parser["some_num"].bind(some_num); //mandatory is implicit

for multi you could bind to a vector.

std::vector some_nums;
parser["some_nums"].bind(some_nums); //multi is implicit

I hope you appreciate my ideas. Let me know if you get tired of them:-)

Peter

mandatory option

I wonder if it would make sense to be able to declare an option as 'mandatory' via a .mandatory() function. I can of course check availability of an option explicitly, but when there are many options, it gets tedious. A missing mandatory options should just throw an exceptions. That way the program can terminate immediately rather than wasting time with other things until it discovers that a critical option is missing.
P.

handling types

Hi josua
I've just started to test your API. Are you receptive to new ideas? If not it's ok, just ignore me. But if you are, here are some ideas:

(1)

O.get().u32

I don't really like the look of the above. Why not simply allows access like this:

O.get<unsigned>()
O.get<double>()
O.get<std::string>()

You have defined a bunch of types yourself, but they pretty much map straight back to c++ types. Why not use the C++ types directly? Use your own types internally only. If the conversion fails, throw an exception. Maybe even better:

if(parser.available("optimization")){
        int o = parser.get<int>("optimization");
}

I think it worth thinking about this. I'm sure its not entirely straight forward, especially in light of interpreting empty string values/ 'null-strings'. I had many such situations in my own code recently, and I usually found that a simple solution was usually possible. I'm happy to discuss.

(2)
Also, personally I don't like the:

auto&& O = parser["optimization"];

I'm not even sure what the auto&& is really for. Is a simple reference not enough?

Thanks, Peter

Visual c++ support

Hi

I develop in visual c++. I have Visual Studio 2015 . You library is not compiling. In fact it crashes the compiler. Have you ever tested your code in Visual Studio? If so, which version are you using. The error looks like this:

1>------ Build started: Project: TS_OPTIMIZER, Configuration: Debug x64 ------
1> opt_main.cpp
1>c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(1845): warning C4244: 'argument': conversion from 'int64' to 'int', possible loss of data
1>c:\users\ritte_pr_dev
\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(1983): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
1>c:\users\ritte_pr_dev
\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(1983): warning C4267: 'initializing': conversion from 'size_t' to 'const int', possible loss of data
1>c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(257): fatal error C1001: An internal error has occurred in the compiler.
1> (compiler file 'msc1.cpp', line 1468)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1> c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(269): note: see reference to class template instantiation 'po::detail::make_integer_sequence_implstd::T,3,false,false,void' being compiled
1> with
1> [
1> T=std::size_t
1> ]
1> c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(271): note: see reference to class template instantiation 'make_integer_sequencestd::size_t,3' being compiled
1> c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(510): note: see reference to class template instantiation 'make_index_sequence<3>' being compiled
1> c:\users\ritte_pr_dev_\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(636): note: see reference to function template instantiation 'bool po::expect<forward_iterator_t,4>(forward_iterator_t &,forward_iterator_t,const char (&)[4])' being compiled
1> with
1> [
1> forward_iterator_t=std::_String_const_iterator<std::_String_val<std::Simple_types>>
1> ]
1> c:\users\ritte_pr_dev
\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(680): note: see reference to function template instantiation 'po::parsing_reportpo::f32_t po::str2flt<T,std::_String_const_iterator<std::_String_val<std::_Simple_types>>,void>(forward_iterator_t,forward_iterator_t)' being compiled
1> with
1> [
1> T=po::f32_t,
1> forward_iterator_t=std::_String_const_iterator<std::_String_val<std::Simple_types>>
1> ]
1> c:\users\ritte_pr_dev
\dev_projects\ts_api_common\source\tsa\program_options\pr_options.h(1224): note: see reference to function template instantiation 'po::parsing_reportpo::f32_t po::str2fltpo::f32_t(const std::string &)' being compiled
1> INTERNAL COMPILER ERROR in 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\CL.exe'
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Compile Error "invalid initialization of non-const reference"

os:

centos 7.2

gcc-c++:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)

ProgramOptions.hxx resp current commit:

7ab12da

use -std=c++11 but:

L112:23: error: invalid initialization of non-const reference of type ‘std::ostream& {aka std::basic_ostream<char>&}’ from an rvalue of type ‘<brace-enclosed initializer list>’
    : m_stream{ stream } {

print() feature request

Hi
Here is some unsolicited feeback.

In general, when one is developing, it is always convenient to be able to print out the state of an object. I think you should have a simple parser::print(std::ostream&) function which prints all option name:value pairs as well as all non-options arguments in a nicely formated, easy to read way. You can never go wrong with a feature like that.

Also, for printing the help, I don't really like the syntax you have have chosen:

std::cout << parser << std::endl;

I think a parser::print_help(std::ostream&) member has better semantics. From the above syntax it is unclear just what exactly is being printed.

Thanks, Peter

Errors when building tests on a Mac

Building on a Mac (macOS 10.13.3), with the default compiler, I get the following errors in tests:

[ 37%] Building CXX object CMakeFiles/Test.dir/test/str2flt.cxx.o
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/test/str2flt.cxx:21:9: error: no matching function for call to 'isinf'
        CHECK( std::isinf( po::str2flt< double >( "15.3e+806" ) ) );
               ^~~~~~~~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:11218:44: note: expanded from macro 'CHECK'
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
                                           ^~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:2155:32: note: expanded from macro 'INTERNAL_CATCH_TEST'
            ( __catchResult <= expr ).endExpression(); \
                               ^~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:431:5: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
    std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity,
    ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:441:5: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
    std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity,
    ^
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/test/str2flt.cxx:21:9: error: no matching function for call to 'isinf'
        CHECK( std::isinf( po::str2flt< double >( "15.3e+806" ) ) );
               ^~~~~~~~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:11218:44: note: expanded from macro 'CHECK'
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
                                           ^~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:2162:60: note: expanded from macro 'INTERNAL_CATCH_TEST'
    } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
                                                           ^~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:431:5: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
    std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity,
    ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:441:5: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
    std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity,
    ^
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/test/str2flt.cxx:42:9: error: no matching function for call to 'isnan'
        CHECK( std::isnan( po::str2flt< double >( "nan" ) ) );
               ^~~~~~~~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:11218:44: note: expanded from macro 'CHECK'
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
                                           ^~~~
/Users/dmitriy/Projects/Upstream/ProgramOptions.hxx/./ext/catch.hpp:2155:32: note: expanded from macro 'INTERNAL_CATCH_TEST'
            ( __catchResult <= expr ).endExpression(); \
                               ^~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:464:25: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
                        ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:472:25: note: candidate template ignored: disabled by 'enable_if' [with _A1 = po::parsing_report<double>]
typename std::enable_if<std::is_integral<_A1>::value, bool>::type
                        ^

These are just the first three, the list goes on. In case it matters,

$ c++ --version
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.