Menu

Removal of static variables

2017-12-10
2020-02-10
  • Paweł Szymański

    So, the problem is that I was trying to test a wrapper of your library I have made for my application.
    Only the first test case was always passing, but every other would fail.

    After a long time of searching I found the culprit. In the file Arg.h there are the following lines:

    /**
     * Indicates whether the rest of the arguments should be ignored.
     */
    static bool& ignoreRestRef() { static bool ign = false; return ign; }
    
    /**
     * The delimiter that separates an argument flag/name from the
     * value.
     */
    static char& delimiterRef() { static char delim = ' '; return delim; }
    

    Some of the tests I wrote were adding "--" (the argument after which every other is ignored) to the arguments sequence.
    I must admit, it was caused by my laziness. I have been using the same utility fuction for both ValueArgs and SwitchArgs.
    For convenience, the default value was that unfortunate double-dash.

    I can fix my tests easily, but I can see many use cases where this behavior will cause problems, for instance:

    • multiple processes parsing their arguments using a deamon parser
    • parsing arguments from multiple sources
    • parsing arguments at different times during program execution

    I wrote an (almost) minimal code example that highlights the issue:

    #include <tclap/CmdLine.h>
    
    #include <iostream>
    
    int main(int argc, const char** argv) {
        {
            TCLAP::CmdLine cmd("First example");
            TCLAP::SwitchArg first_arg("f", "first", "first switch argument", cmd);
            TCLAP::SwitchArg second_arg("s", "second", "second switch argument", cmd);
    
            int first_argc = 3;
            const char** first_argv = new const char* [first_argc];
            first_argv[0] = "/nowhere";
            first_argv[1] = "--first";
            first_argv[2] = "--";
            cmd.parse(first_argc, first_argv);
            delete[] first_argv;
    
            std::cout << "First example: first=" << first_arg.getValue() << ", second=" << second_arg.getValue() << std::endl;
        }
    
        {
            TCLAP::CmdLine cmd("Second example");
            TCLAP::SwitchArg first_arg("f", "first", "first switch argument", cmd);
            TCLAP::SwitchArg second_arg("s", "second", "second switch argument", cmd);
    
            int second_argc = 3;
            const char** second_argv = new const char* [second_argc];
            second_argv[0] = "/nowhere";
            second_argv[1] = "--second";
            second_argv[2] = "--";
            cmd.parse(second_argc, second_argv);
            delete[] second_argv;
    
            std::cout << "Second example: first=" << first_arg.getValue() << ", second=" << second_arg.getValue() << std::endl;
        }
    
        return 0;
    }
    

    It produces the following output:

    First example: first=1, second=0
    Second example: first=0, second=0

    Where it should be:

    First example: first=1, second=0
    Second example: first=0, second=1

     
  • Daniel Aarno

    Daniel Aarno - 2018-01-02

    Yea, that's annoying. I've created https://sourceforge.net/p/tclap/bugs/25/ to track this issue.

     
  • Daniel Aarno

    Daniel Aarno - 2020-02-10

    This specfic problem is fixed in [2a4ae2] (test case now pass).

     

    Related

    Commit: [2a4ae2]


Log in to post a comment.