Avoid typing really much arguments?

时间:2015-06-25 18:28:08

标签: c++

void logVar(var a) {
    var z;
    z = a.toString();
    printf("%s ", z._chr().getUtf());
}

void log(var a, 
    var b = argIgnore, var c = argIgnore, var d = argIgnore,
    var e = argIgnore, var f = argIgnore, var g = argIgnore,
    var h = argIgnore, var i = argIgnore, var j = argIgnore,
    var k = argIgnore, var l = argIgnore, var m = argIgnore,
    var n = argIgnore, var o = argIgnore, var p = argIgnore,
    var q = argIgnore, var r = argIgnore, var s = argIgnore,
    var t = argIgnore, var u = argIgnore, var v = argIgnore,
    var w = argIgnore, var x = argIgnore, var y = argIgnore,
    var z = argIgnore, var A = argIgnore, var B = argIgnore
    )
{
    logVar(a);  
    if (b.type != varIgnore) logVar(b);
    if (c.type != varIgnore) logVar(c);
    if (d.type != varIgnore) logVar(d);
    if (e.type != varIgnore) logVar(e);
    if (f.type != varIgnore) logVar(f);
    if (g.type != varIgnore) logVar(g);
    if (h.type != varIgnore) logVar(h);
    if (i.type != varIgnore) logVar(i);
    if (j.type != varIgnore) logVar(j);
    if (k.type != varIgnore) logVar(k);
    if (l.type != varIgnore) logVar(l);
    if (m.type != varIgnore) logVar(m);
    if (n.type != varIgnore) logVar(n);
    if (o.type != varIgnore) logVar(o);
    if (p.type != varIgnore) logVar(p);
    if (q.type != varIgnore) logVar(q);
    if (r.type != varIgnore) logVar(r);
    if (s.type != varIgnore) logVar(s);
    if (t.type != varIgnore) logVar(t);
    if (u.type != varIgnore) logVar(u);
    if (v.type != varIgnore) logVar(v);
    if (w.type != varIgnore) logVar(w);
    if (x.type != varIgnore) logVar(x);
    if (y.type != varIgnore) logVar(y);
    if (z.type != varIgnore) logVar(z);
    if (A.type != varIgnore) logVar(A);
    if (B.type != varIgnore) logVar(B);
    printf("\n");
    fflush(0);
}

Is there a way to achieve the same with less typing?

The option is to generate this entire code from a script. (That's the only way to be sure there are no typos survived).

UPDATE:

I think I should have given much more detail in my question. I never seen a question getting 7 downvotes in just a couple of minutes.

The var class I am using is a JavaScript like class for my own library, the instance of var can hold either number or a string or an array or an object, or boolean. It has a constructor which can construct from any of those types and some more, including enum special { argIgnore }.

So when constructor var::var(special) is called, (which is the default for log(), the variable is considered ignored. This allows to use the log() function like this:

var a = 1;
var b = "hello";
var c = arr;
c.push(100);
c.push(200);
log(a, b, c, 500, "world");

This call will print:

1 hello 100, 200, 500, world

Using varargs/stdargs is not possible here, because varargs cannot call constructors on arguments.

Using vectors or other sort of preset structures is not useful for my case, because this is a syntactic sugar what I am trying to achieve.

2 个答案:

答案 0 :(得分:4)

This does much the same thing. Extra work is done in case you pass in things that can be converted to var but are not var. About the only difference is any such temporary var have a shorter lifetime.

// acts on a `var` if it is not `varIgnore`:
template<class F>
void on_var( var const& v, F&& f ) {
  if (v.type != varIgnore)
    std::forward<F>(f)(v);
}
// logs 1 or more vars out:
template<class...Vars>
void log(var a, Vars&&...vars) {
  logVar(a);
  // this strange syntax runs the on_var for each
  // argument in the ...vars parameter pack by expanding
  // the pack into an array of integers (all full of 0s), which
  // is then discarded.  The array creation has no side effects, so
  // under any optimization settings, the array isn't actually created,
  // but the operations are still done.  C++1z has improved ways
  // to do this:
  using discard=int[];
  (void)discard{0,(
    on_var(std::forward<Vars>(vars), [](var const&v){logVar(v);})
  ,0)...};
  printf("\n");
  fflush(0);
}

if things convertible to var are not valid parameters, a simpler solution works:

template<class...Vars>
void log(var a, Vars...vars) {
  logVar(a);
  using discard=int[];
  (void)discard{0,(
    (vars.type != varIgnore)?(logVar(vars),0):0
  )...};
  printf("\n");
  fflush(0);
}

with no need for on_var function. However, your clarification seems to indicate that things-converted-to var have to work.

live example.

var is written as an example "any type of variable" class with a meaningful toString. I modified logVar, but the modifications shouldn't matter much.

答案 1 :(得分:0)

Suggestions I feel this is a much more simpler and OOP approach than the templates approach, although I see someone did a nice job at a template version :) Its much more common and considered best-practice to use a class for the argument list than a large list of variables. As you have already experienced, it is a difficult to maintain and use. My suggestion would be change the interface of logvar() Instead of this: logvar(var a, var b, ...) You would probably thank yourself later to change this to: logvar(LogData& data) Then you could have a class LogData that held all your variables and you can handle the logic without changing the interface. If you ever need to add or remove a variable, it is done in LogData and not in the function argument list. Personal Feeling about default arguments I prefer default arguments after something has been implemented and I come back and realize there should be something else, this can be a great place-holder when you are in a pinch and need to get something done.... But it makes it difficult for the next person who comes along because its one more little thing that isn't obvious in the code when you are reading and happen to encounter it being used.