# Yet another FizzBuzz

Since today is apparently a good day for...unlikely FizzBuzz implementations, I decided to contribute another, this one in C++:

#include <iostream>
#include <functional>
#include <vector>
#include "xrange.h"

int main() {
std::vector<std::function<void(int)> > funcs {
[](int i) { std::cout << i << "\n"; },
[](int i) { std::cout << "fizz\n";  },
[](int i) { std::cout << "buzz\n";  },
[](int i) { std::cout << "fizzbuzz\n"; }
};

auto test = [](int i){return (i % 3 == 0) + 2 * (i % 5 == 0); };

for (auto i : xrange(1, 101))
funcs[test(i)](i);
}


This uses the same xrange I posted in a previous answer.

I'd be particularly interested in eliminating having to use test, but a sequence like: [[ is parsed as introducing an attribute rather than using the return from a lambda as an index (and inserting white space doesn't seem to help). I could use .at() instead, but that imposes runtime overhead I'd also rather avoid.

-
Did you try extra paranthesis: funcs[([]...)]? Note that anything using a lambda in the index brackets is basically obfuscation. – Nobody Jul 12 '14 at 19:25
@Nobody: Yes, I did, but couldn't find a way g++ would accept it. – Jerry Coffin Jul 12 '14 at 19:26
As it is already ugly with the lambda you could get it to work with some arithmetic: funcs[0+[](int... and when talking about ugliness you could also use the explicit operator name: funcs.operator[]([]... – Nobody Jul 12 '14 at 19:32
@Nobody: Neither of these options strikes me as an improvement (but opinions obviously vary--I don't find lambdas ugly at all). – Jerry Coffin Jul 12 '14 at 19:39
So you say that (if it would work) you would prefer to use:funcs[[](int i){return (i % 3 == 0) + 2 * (i % 5 == 0); }(i)] over funcs[(i % 3 == 0) + 2 * (i % 5 == 0)] (which is already a mess)? – Nobody Jul 12 '14 at 19:41

I'd be inclined to make a simple fixed array instead of a std::vector for funcs:

const std::function<void(int i)> funcs[] {
[](int i) { std::cout << i << "\n"; },
[](int ) { std::cout << "fizz\n";  },
[](int ) { std::cout << "buzz\n";  },
[](int ) { std::cout << "fizzbuzz\n"; }
};


This is useful because it eliminates the overhead of memory allocations for a std::vector and the calls for constructor and destructor. As an embedded systems guy, I tend to think about whether code can be in ROM rather than RAM, and whether work can be done at compile-time rather than run-time.

Note, too that I've omitted the variable name for the last three lambdas. There's no real difference except that it prevents the compiler from generating a warning about "unused parameter i" in those three lines.

Also, I think you're overthinking the lambda. The test lambda isn't really necessary at all since you can call it like this:

funcs[ (i % 3 == 0) + 2 * (i % 5 == 0) ](i);


So (without xrange.h, although one could use that also) it would look like this:

#include <iostream>
#include <functional>

int main() {
const std::function<void(int i)> funcs[] {
[](int i) { std::cout << i << "\n"; },
[](int ) { std::cout << "fizz\n";  },
[](int ) { std::cout << "buzz\n";  },
[](int ) { std::cout << "fizzbuzz\n"; }
};

for (int i=1; i <= 100; ++i)
funcs[ (i % 3 == 0) + 2 * (i % 5 == 0) ](i);
}

-
Are you using a C-style array for brevity, or because you're trying to avoid giving it an explicit size? – Jamal Jul 12 '14 at 20:41
I meant std::array, actually (sorry, I should've made that clear). – Jamal Jul 12 '14 at 21:26
@Jamal: std::array and a C-style array would be very similar in this context, but I used the C-style array just because it seems to me to be a clearer way to express the idea. Memory usage and performance would likely be identical, so we can attribute the choice to aesthetic preference. – Edward Jul 12 '14 at 21:43