lundi 3 août 2015

Can Template / Preprocessor hackery be used to support variable arguments in the middle of an argument list?

I have stumbled upon old code that looks like this:

void dothing(bool testBool,
               const std::string& testString1,
               const std::string& file,
               int line,
               const std::string& defaultString = "")
{
     // do something...
}

void dothings(bool testBool,
               const std::string& testString1,
               const std::string& testString2,
               const std::string& file,
               int line,
               const std::string& defaultString = "")
{
    dothing(testBool, testString1, file, line, defaultString);
    dothing(testBool, testString2, file, line, defaultString);
}

void dothings(bool testBool,
               const std::string& testString1,
               const std::string& testString2,
               const std::string& testString3,
               const std::string& file,
               int line,
               const std::string& defaultString = "")
{
   dothings(testBool, testString1, testString2, file, line, defaultString);
   dothing(testBool, testString3, file, line, defaultString);
}

void dothings(bool testBool,
               const std::string& testString1,
               const std::string& testString2,
               const std::string& testString3,
               const std::string& testString4,
               const std::string& file,
               int line,
               const std::string& defaultString = "")
{
   dothings(testBool, testString1, testString2, testString3, file, line, defaultString);
   dothing(testBool, testString1, file, line, defaultString);
}

It is ridiculous and I am trying to refactor it to be:

 void dothings(bool testBool,
              std::initializer_list<std::string> testStrings,
              const std::string& file,
              int line,
              const std::string& defaultString = "")
{
    for(auto iter = testStrings.begin(); iter != testStrings.end(); ++iter)
    {
        dothing(testBool, *iter, file, line, defaultString);
    }
}

The problem is that those functions are used a lot and I would like to write a macro or template in such a way that all of the previous functions construct an initializer list of strings of all of the test strings and pass them to the one new function. I want to write something like this:

#define dothings(testBool, (args), file, line) dothings(testBool, {args}, file, line)

I don't really care about the default string in these functions, but if there is a way to support it, that would be great.

I have access to a c++11 compiler and boost.

I have seen some interesting posts about variable argument macros, but It's just not clicking how to apply them to this case.

Aucun commentaire:

Enregistrer un commentaire