Process an unknown number of undefined objects for logging

When trying to reproduce something that in C # you would do something like this:

 string FormatString(params object[] args) {
      return string.Format(CultureInfo.InvariantCulture, args);
 }

      

And in Obj-c it will look like this:

#include <stdarg.h>

void logObjects(id firstObject, ...) {
    va_list args;
    va_start(args, firstObject);
    id obj;
    for (obj = firstObject; obj != nil; obj = va_arg(args, id))
        NSLog(@"%@", obj);
    va_end(args);
}

logObjects(@"foo", [NSNumber numberWithInt:4], @"bar", nil);

      

I'm familiar with variable length parameter, but not too sure how to store the arguments and then send them to std :: cout. Is it possible?

Note! I want to send any object that the <<operator can handle. Just look at this function as a replacement:

std::cout << "test" << someObject << int << someOtherObject; 

      

I am using boost and want it to be platform independent. This function will be part of the log class in the shared lib.

+3


source to share


3 answers


It doesn't work in C # either, because the format string is missing, the concept is clear anyway. In C, you can do something like this (as shown in dbgprint if you have a variadic macro function)

#define printfex(...) printf(__VA_ARGS__)

      



If you are so fortunate to be using C ++ 11 , you can write this prototype:

template<class... T>
void printfex(const std::string& format, T... args);

      

+2


source


Sorry, but I don't know very much about C #. Do you want to send a list of parameters std::cout

? This is not difficult:

void formatString (const std::vector<std::string>& args)
{
    for (int i=0; i<args.size (); ++i)
    {
        std::cout << args[i];
    }
    std::cout << std::endl;
}

      

And you can store items like this:

std::vector test (2);
test[0] = "one";
test[1] = "two";
formatString (test);

      



UPDATE

Copy and paste this into a .cpp file and compile it. You must implement an interface IPrintable

for each class you want to write. It may not be the most efficient solution, but it works.

#include <iostream>
#include <string>
#include <vector>

class IPrintable
{
public:
    virtual ~IPrintable () { }

    virtual std::string toString () const = 0;
};

class ClassA : public IPrintable
{
public:
    std::string toString () const
    {
        std::string s = "Class A to string";
        return s;
    }
};

class ClassB : public IPrintable
{
public:
    std::string toString () const
    {
        std::string s = "Class B to string";
        return s;
    }
};

void print (const std::vector<IPrintable*> args)
{
    for (int i=0; i<args.size (); ++i)
    {
        std::cout << args[i]->toString () << std::endl;
    }
}

int main (int argc, char* argv[])
{
    ClassA a;
    ClassB b;

    std::vector<IPrintable*> v (2);
    v[0] = &a;
    v[1] = &b;

    print (v);
    return 0;
}

      

+1


source


You cannot use runtime parameter variables in C ++ - this is a basic fact. You should use the same technique as C ++ streams - operator overloading. Fortunately, C ++ already contains this functionality.

void f(const std::stringstream& str) {
    std::cout << str;
}
int main() {
    int i = 5;
    f(std::stringstream() << "i is equal to " << 5);
}

      

+1


source







All Articles