User Tools

Site Tools


info:cxx_libraries

C++ Package/Dependency Managers

Option / Argument Parsing

  • QCommandLineParser - built in to Qt5
  • Clara (from Catch2 testing framework) [C++11] [single header]
    • Composable - "Each Opt or Arg is an independent parser. Combine these to produce a composite parser - this can be done in stages across multiple function calls - or even projects."
    • Header-only, but multiple header files
    • Has some explicit support for positional arguments (UnlabeledValueArg, UnlabeledMultiArg)
    • Definition seems a bit clunky (help text definition looks too manual)
    • Small (single header file)
  • https://github.com/jarro2783/cxxopts (MIT license) [C++11] [single header]
    • Value types are repeated in the definition and the "get"
    • Limited documentation
    • No mention of enumerated values
  • ezOptionParser (MIT license) [single header]
    • Multiple options for generated help text layout
    • Looks like it stores positional arguments in two lists depending on where they appear: firstArgs and lastArgs
  • https://github.com/Taywee/args [C++11] [single header]
    • Lots of macros
    • Can define flags in a library and use in multiple applications
    • Multiple options for help output
    • Options to read values from environment or from a file
    • Modifies argv/argc to support positional arguments
    • Requires library (not header-only); they have RPMs with static and shared libraries (not sure if they're RHEL5-compatible)
  • QtArg (uses Qt, obviously)
    • Generates help text; not perfect (to my taste) but okay
    • Header-only, so easy to add to project
    • Docs not extensive, not online, but source includes a Doxyfile for building Doxygen docs
    • Contains some messages with awkward English. For example: "Not defined value of the argument:". Submit patch/suggestions?
  • Boost.Program_options
    • Not header-only–requires library
  • http://code.jellycan.com/simpleopt/ (I have not tried this yet, but I like SimpleINI)
    • It does not generate help text

Configuration Files

    • Usually it's required to compile one file, ConvertUTF.c, and have ConvertUTF.h available (as far as I can tell, this is avoidable if libicu is available or if on Windows); SimpleINI itself is header-only
    • ConvertUTF.h typedef of Boolean conflicts with X11 headers
    • Built-in parsers for integer, double, and bool values (GetLongValue, GetDoubleValue, GetBoolValue)
      • Annoyance: no float/double parsing "Get" - looks like it has GetDoubleValue now
    • Preserves ordering and comments when writing
    • Using it directly will pollute the namespace a bit, and may slow down compilation (probably not significantly). Could use a simple wrapper.
  • Boost.Program_options does INI files (in addition to command-line options)
  • Boost.PropertyTree can read and write XML, JSON, and INI files
  • libconfig - looks like a nice solution for more structured configuration files
  • For anything more complicated than an INI file, I would probably prefer to use something like YAML or JSON
  • QSettings
    • Probably good for Qt, especially things like position and size of windows
    • Does some Qt-specific things, so might not be compatible with other INI readers/writers (then again, other readers/writers do similar things)
    • Does not preserve comments
  • KConfig (part of KDE Frameworks 5)

JSON

JSON specification: http://tools.ietf.org/html/rfc4627.html

    • Public Domain
    • The output formatting is pretty good
    • Available as an "amalgamation" (single cpp file, two h files) for easy inclusion in a project
    • Objects keys are always written in alphabetical order
    • Has the option to get specific parsing errors with line number
  • RapidJSON - "A fast JSON parser/generator for C++ with both SAX/DOM style API"
    • Header-only, no external dependencies
    • Header-only, C++11
    • Nice-looking syntax
  • QJson - uses QVariants; can serialize and deserialize properties from Q_OBJECT subclasses
    • Output formatter is not very good (as of 2011-05)
    • Minimal parsing error messages
    • Prints some things to the console
    • To help me switch from this to JsonCpp, I wrote https://github.com/samh/JsonCppQt
  • JSON Spirit - uses Boost
    • Usable as a library or header-only
    • Download requires login to CodeProject site
    • Has the option of user either vector or map for objects; vector allows maintaining the order of the keys
    • Can read multiple top-level values from streams
    • Has the option to get specific parsing errors with line number
  • Jansson - appears to be a good-quality C library
  • json-c - another C library
  • A few others found from a search for "c++ json":

Unit Testing, Mocking

Google Test (plus Google Mock) seems to be the most promising, and the documentation for both is excellent. Also, it's supported by Eclipse CDT as of the Juno release, as well as in JetBrains CLion.

CATCH, first released in December 2010 (added by the author to the first StackOverflow question linked below), has some very nice features, like being header-only and naming tests with strings. See also the release blog post.

Qt Test might be worth looking at for the GUI simulation features.

Other options:

Relevant Stack Overflow topics:

List: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B

Eclipse Support

CDT 8.1 (Eclipse 4 Juno, 2012-06) adds some unit testing support. See:

Supported libraries (as of 2012-06):

  • Boost.Test
  • Qt Test
  • Google Test

Code Coverage

Mocking

  • FakeIt - single-header library, C++11, can integrate with various unit test frameworks (Catch, Google Test, etc.)
    • Incomplete / may have limited compiler/architecture support
  • TypeMock Isolator++ (~$600) looks pretty powerful
    • 32-bit only 1)

Google Mock

https://github.com/google/googletest (now part of Google Test repository)

This is a bit more verbose to get set up than some of the others, but the documentation is extensive.

gmock_gen

The gmock_gen.py script can generate mock object definitions, but is a bit limited. Sometimes I've seen "No class found" errors; you may be able to resolve these by commenting out more complicated bits of the file (e.g. I had a forward-declaration "typedef struct").

To change the indentation, set the INDENT environment variable, e.g.:

INDENT=4 gmock_gen.py header-file.h ClassName

Hippo Mocks

Hippo Mocks appears to be less verbose in some cases than Google Mock.

Some old news at http://www.hippomocks.com/news/.

A newer version is available in git (https://github.com/dascandy/hippomocks; looks like Assembla one is no longer used: https://www.assembla.com/code/hippomocks/git/nodes/master).

  • Unlike gmock, you don't have to declare a class and each of the methods (gmock requires that you do this explicitly, either manually, or they have a Python script that will try to generate them for you, but you would have to do it each time the interface changed).
  • The expectations can be more verbose than gmock.
  • The error messages don't seem to be as nice as gmock (in particular the formatting is lacking).
  • There is very little documentation (just a tutorial; unit tests serve as the examples).
    • I had trouble getting it to work as expected; the error messages about expectations didn't make sense enough to allow me figure it out. Specifically the message "Function called without expectation".
  • Problems with overridden functions

Logging

log4cxx

This is an Apache project.

It's basically dead. There are a few user who would like to revive it (see dev mailing list around 2011-01), but nothing much happening yet. There are a few forks; see https://github.com/apache/log4cxx/network/members.

Pro

  • Apparently uses exactly the same configuration file format as log4j.
  • Ubuntu package available

Con

Notes

Static lib (compiled on RHEL5) is 21MB.

Compiled on CentOS4 by also compiling apr and apr-util. Probably should use static libraries for all 3? These also appeared to work on RHEL5.

google-glog

  • Provides RPMs and DEBs; library is very small
  • Some interesting things; possibly worth looking at and replicating for use with other logging libraries
    • LOG_EVERY_N
    • Assertion ("CHECK") macros
    • Appears to automatically separate logging into "modules" (by filename) that can be used to turn logging on and off (rather than explicitly specifying a "logger" object as with log4*-style libraries)
    • Failure Signal Handler that prints a stack trace
    • On FATAL log messages, it tries to print a stack trace before aborting
  • Minimal configuration options
  • Configuration from command-line; possibly useful for command-line heavy utilities (for which I typically avoid C++)
  • Doesn't follow the log4j "model"
  • Seems like RHEL4 compiler may be too old

Log4cplus

log4cplus; see also forum at SourceForge; code is in SVN at SourceForge

Does not seem to be that well-documented, but not terrible (everything in Doxygen docs).

File-based configuration similar to, but not the same as, log4j.

On 2010-11-08 I looked at it again, and it's not so bad, though it has its quirks. Using it seems like it would be easier than log4cxx, since it doesn't have the apr dependencies (seems to work fine on RHEL4, but that's no so much an issue any more). The static library is 4.2 MB on RHEL4, and the shared library is smaller; it would probably be a good candidate for creating an RPM (update: I created an RPM for RHEL5; it was basically just rpmdev-newspec -t lib log4cplus and fill in the top section).

Also, the source code is not bad to look at.

Questions

  • Is it possible to define a variable in the property configuration file, to later substitute in one or more places?

Quirks

  • Links in documentation to "manual.html" are broken
  • "%M" (PatternLayout) is documented but not implemented
  • It would significantly help navigation (i.e. keeping multiple tabs open) if the title in the doxygen docs were unique to the page, rather than always "Log4cplus Project Page".
  • Configuration examples (in PropertyConfigurator docs) were wrong (needed to use "::" for namespaces; found out by trial & error).
    • Update: the namespace separator seems to be correct (now, at least) in the source file, but maybe Doxygen is messing it up.
    • Bad example: log4cplus.appender.A2.layout.DateFormat=ISO8601 (this doesn't work)
  • Documentation for %d indicates that it has a default, which doesn't seem to work (this seems to have been my error; it's working as expected now)
  • Documentation for TTCC layout could use updating
    • See code in layout.cxx for exactly what goes into the layout
    • Uses a different default date format from %d in PatternLayout
    • The example using TTCC layout in PropertyConfigurator appears to be incorrect (2011-04-18)
  • You can set the threshold for a particular appender; I use this to make the console appender less verbose. As of 1.0.4, the property has to be capitalized ("Threshold" instead of "threshold"), which seems to be inconsistent with other properties (cf. appender.cxx).

Notes

  • ConfigureAndWatchThread is not documented but works fine. Just make sure to keep around the instance (e.g. allocate on heap, keep a reference). It spawn a thread (another class), but it's stopped if the ConfigureAndWatchThread object is destroyed.
  • When using PatternLayout, "%D" is local time, "%d" is UTC

log4cpp

Available in RHEL5 base repository.

Doesn't appear to have been updated in a while.

Boost.Log

Probably worth a second look. Not yet part of the Boost library, but provisionally accepted. Might be better to wait and see if some of the changes proposed in the review announcement are implemented (as of Dec. 2010, it looks like it may be a while).

Others

C++ String Library

std::string sucks, and QString makes your program depend on Qt, so what do you do? I would ask on Stack Overflow, but someone did it already: Good C++ string manipulation library.

Boost string libraries are probably a good choice in many cases, but for a standalone project I might like to try one of the other suggestions.

Boost Format

I've been thinking about ways of using the Boost Format library with logging to make formatted output easier and to make it easier to replace uses of printf in old code. One problem is with the use of "%", so it's not so simple to just do a find/replace.

A possible solution was posted at http://www.gamedev.net/topic/477256-boostformat-overkill/, using the Boost preprocessor library to write templates; the snippet below is slightly modified so it compiles:

#include <iostream>
#include <string>
 
#include <boost/format.hpp>
#include <boost/preprocessor.hpp>
 
class logger_t
{
public:
   void write(const std::string& s)
   {
      std::cout << s << "\n";
   }
 
   void write(const boost::format& f)
   {
      write(boost::str(f));
   }
 
#  define BOOST_PP_LOCAL_MACRO(n) \
       template<BOOST_PP_ENUM_PARAMS(n, typename T)>                             \
       void write(std::string str BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(n, const T,& t)) \
       { \
           write(boost::str(boost::format(str) BOOST_PP_REPEAT(n, MAKE_FORMAT_ARGS, ~))); \
       } \
   /**/
 
#  define MAKE_FORMAT_ARGS(z, n, unused) % t##n
 
#  define BOOST_PP_LOCAL_LIMITS (1, 10)
#  include BOOST_PP_LOCAL_ITERATE()
#  undef MAKE_FORMAT_ARGS
};
 
int main()
{
    logger_t logger;
    logger.write( "Setting video mode: %dx%dx32 %s", 320, 240, "fullscreen");
}

The resulting function templates could then, presumably, be called from a variadic macro.

Since I'm also using cog.py for some other things, I might consider using it to do something similar. Using cog.py would make it easier to understand (since you see the output, without having to run g++ -E) and also should be usable in Eclipse without code analysis errors.

Below is a cog version of the same thing (with max_params set artificially low for demonstration, and cog.py already run):

class logger_t {
public:
    void write(const std::string& s) {
        std::cout << s << "\n";
    }
 
    void write(const boost::format& f) {
        write(boost::str(f));
    }
 
    /*[[[cog
    max_params = 3
 
    template = """
    template<%s>
    void write(const std::string& str, %s) {
        write(boost::str(boost::format(str) %% %s));
    }
    """.strip()
 
    for param_count in xrange(1, max_params + 1):
        typenames = ', '.join(["typename T%d" % i for i in xrange(param_count)])
        args = ', '.join(["const T%d & t%d" % (i, i) for i in xrange(param_count)])
        format_args = ' % '.join(["t%d" % i for i in xrange(param_count)])
 
        cog.outl(template % (typenames, args, format_args))
    ]]]*/
    template<typename T0>
    void write(const std::string& str, const T0 & t0) {
        write(boost::str(boost::format(str) % t0));
    }
    template<typename T0, typename T1>
    void write(const std::string& str, const T0 & t0, const T1 & t1) {
        write(boost::str(boost::format(str) % t0 % t1));
    }
    template<typename T0, typename T1, typename T2>
    void write(const std::string& str, const T0 & t0, const T1 & t1, const T2 & t2) {
        write(boost::str(boost::format(str) % t0 % t1 % t2));
    }
    //[[[end]]]
};
 
int main() {
    logger_t logger;
    logger.write("Setting video mode: %dx%dx32 %s", 320, 240, "fullscreen");
}

Template Engine

Cryptography

  • libsodium seems to be well-regarded
    • Used in ZeroMQ
    • Used in SQRL 2)
    • Bindings are available for most languages

Database

For standard database connectivity, I've mostly used Qt's database classes. SOCI looks interesting; it has Oracle and PostgreSQL backends, but the ODBC backend is unsupported.

ORM

See "Good ORM for C++ solutions?" on StackOverflow.

Last time I looked there were some new links that looked interesting:

  • QxOrm (uses Boost and Qt) - no code generation, superclass, or XML mapping
  • Debea - uses macros and a superclass
  • ODB - uses precompiler; license is GPL/Commercial
  • QDjango - uses QObject models
  • LiteSQL (SQLite3, PostgreSQL and MySQL) - objects defined by XML files
  • hiberlite (SQLite only)

Embedded Data Stores

These all have bindings for other languages as well.

  • SQLite
    • Multi-thread, multi-process
    • Multi-thread, single process

Miscellaneous

  • Better Enums - single header "reflective enum types" - convert to and from strings, loop over values

Boost.Units

libqxt

LibQxt seems to have a lot of random Qt-based add-on functionality.

I first found this library from a StackOverflow question asking about command-line option parsers, which pointed to QxtCommandOptions, but it looks like that particular class has been removed.

Boost.Optional

Boost.Optional seems like a good, general way to represent nullable member variables.

checkedthreads

a free framework for parallelizing C and C++ code, and for automatically finding every race condition that could potentially manifest on given program inputs.

Blog post: http://www.yosefk.com/blog/checkedthreads-bug-free-shared-memory-parallelism.html

Source: https://github.com/yosefk/checkedthreads

info/cxx_libraries.txt · Last modified: 2018-01-08 17:55 by sam