#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <ctime>

class SimpleObject 
{
    int _int;
    float _float;

public:
    SimpleObject() : _int(0), _float(0.0f) {}

    int GetInt() { return _int; }
    float GetFloat() { return _float; }

    void incrementInt() { ++_int; }
    void incrementFloat() { _float += 1.0f; }
};

std::size_t getCount(const std::string& prompt)
{
    std::string Input;

    std::cout << prompt << "\n> ";

    std::getline(std::cin, Input);

    if (Input == "exit")
        return 0;

    return std::stoi(Input);
}

void doForLoop(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
    {
        for (auto it = v.begin(); it != v.end(); ++it)
        {
            it->incrementFloat();
            it->incrementInt();
        }
    }
}

void doForEach(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
        for_each(v.begin(), v.end(), [](SimpleObject& o) { o.incrementFloat(); o.incrementInt(); });
}

void doRangedFor(std::vector<SimpleObject>& v, std::size_t iterations)
{
    for (std::size_t i = 0; i < iterations; ++i)
        for (auto & e : v)
            e.incrementFloat(), e.incrementInt();
}

using func_type = void(*)(std::vector<SimpleObject>&, std::size_t);
void test(const std::string& testName, func_type testme, std::size_t iterations, std::size_t objects)
{
    std::vector<SimpleObject> v(objects);

    clock_t begin = clock();
    testme(v, iterations);
    clock_t end = clock();

    std::cout << "Test \"" << testName << "\" took " << (float(end) - begin) / CLOCKS_PER_SEC << " seconds.\n";
}


int main(int argc, char** argv) 
{
    std::size_t nIterations;
    std::size_t nObjects;

    do 
    {
        nIterations = getCount("Enter the number of iterations:");
        nObjects = getCount("Enter the number of objects in the container:");

        if (nIterations && nObjects)
        {
            std::cout << "\n\nWe will be performing " << nIterations << " iterations on a container holding ";
            std::cout << nObjects << " objects.\n";

            test("for loop", doForLoop, nIterations, nObjects);
            test("for each", doForEach, nIterations, nObjects);
            test("ranged for", doRangedFor, nIterations, nObjects);
        }
    } while (nIterations && nObjects);
}