Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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.

share|improve this question
    
Did you try extra paranthesis: funcs[([]...)]? Note that anything using a lambda in the index brackets is basically obfuscation. –  Nobody Jul 12 at 19:25
    
@Nobody: Yes, I did, but couldn't find a way g++ would accept it. –  Jerry Coffin Jul 12 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 at 19:32
2  
@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 at 19:39
1  
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 at 19:41
show 3 more comments

1 Answer 1

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);
}
share|improve this answer
    
Are you using a C-style array for brevity, or because you're trying to avoid giving it an explicit size? –  Jamal Jul 12 at 20:41
    
@Jamal: updated my answer to address your question. –  Edward Jul 12 at 21:16
    
I meant std::array, actually (sorry, I should've made that clear). –  Jamal Jul 12 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 at 21:43
    
Yeah, that's what I figured (so it does answer my question). –  Jamal Jul 12 at 21:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.