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.
source to share
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);
source to share
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;
}
source to share
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);
}
source to share