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

class StopWatch
{
public:
	struct Process
	{
		Process(std::string name, double time)
			:process_name(std::move(name)),
			running_time(time)
		{}
		
		std::string process_name;
		double running_time;
	};
	
	StopWatch()
		:running_(false)
	{}

	void Start(const std::string & process)
	{
		if (running_)
			Stop();
		current_process_ = process;
		running_ = true;
		start_time_ = std::chrono::system_clock::now();
	}
	
	void Stop()
	{
		if (!running_)
			return;
		auto now = std::chrono::system_clock::now();
		std::chrono::duration<double> duration = now - start_time_;
		processes_.emplace_back(
			std::move(current_process_), duration.count());
		running_ = false;
	}
	
	static double SystemClockSeconds()
	{
		
		return (double)clock() / CLOCKS_PER_SEC;
	}
	
	double operator[] (const std::string & process) const
	{
		auto it = std::find_if(
			processes_.begin(), processes_.end(),
			[&](const Process & p) {
				return p.process_name == process;
			});
			
		if (it != processes_.end())
			return it->running_time;
		return 0.0;
	}
	
	Process operator[](int index) const {
		return processes_[index];
	}
	
	int size() const { return processes_.size(); }
private:
	bool running_;
	std::string current_process_;
	std::chrono::system_clock::time_point start_time_;
	std::vector<Process> processes_;		
};

std::ostream & operator<<(
	std::ostream & os, const StopWatch & watch)
{
	for (int i=0; i<watch.size(); ++i)
		os << watch[i].process_name << " : "
		   << watch[i].running_time << "s\n";
	return os;
}

int main()
{
	const int sz = 1000000;
	std::vector<long long> src;
	std::vector<long long> vi;
	std::vector<long long*> vp;
	
	for (int i=0; i<sz; ++i)
	{
		int x = rand();
		src.push_back(x);
		vi.push_back(x);
	}
	
	for (int i=0; i<sz; ++i)
	{
		vp.push_back(&src[i]);
	}
	
	StopWatch watch;
	watch.Start("integers");
	std::sort(vi.begin(), vi.end(),
	    [](long long lhs, long long rhs) {
			return lhs < rhs;
		});
	watch.Stop();
	
	watch.Start("pointers");
	std::sort(vp.begin(), vp.end(),
	    [](long long * lhs, long long * rhs) {
			return *lhs < *rhs;
		});
	watch.Stop();
	
	std::cout << watch;
}