// Simple program to compare between four functions that support "Variable Arguments" feature ,
// using four different techniques
// Abdullah Alshammari
// aboshammar@gmail.com
// 7/Sep/2010
// First release .

#include <stdarg.h>
#include <iostream>
#include <vector>
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <boost/array.hpp>
using namespace std;

template <typename T>
class DynamicArray
{
	T *a;
	int size; // max size
	int length; // current length
public:
	DynamicArray<T>(int size)
		:size(size),length(0)
	{
		// suppose that there is no exception to throw !
		a = new T[size];
	}
	bool add(const T &value){
		if(length > size) return false;
		a[length++] = value;
		return true;
	}
	const T& get(int index) const{
		assert(index < length );
		return a[index];
	}
	int getLength() const{
		return this->length;
	}
};

template<typename T> T sumVector(const std::vector<T> &numbers)
{
	T total = 0;
	for(std::size_t i = 0; i < numbers.size(); i++) {
		total = total + numbers[i] ;
	}
	return total;
}

template<typename T> T sumMacro(int length, ...)
{
	va_list vList;
	va_start(vList, length);
	T total = 0;
	for(int i = 1; i <= length; i++) {
		int a = va_arg(vList, T);
		total = total + a ;
	}
	va_end(vList);
	return total;
}

template<typename T> T sumDynamicArray(const DynamicArray<T> &numbers)
{
	T total = 0;
	for(int i=0;i<numbers.getLength();i++){
		total = total + numbers.get(i);
	}
	return total;
}

template<typename T,std::size_t E> T sumBoostArray(const boost::array<T,E> &numbers)
{
	T total = 0;
	for(std::size_t i=0;i<numbers.size();i++){
		total = total + numbers[i];
	}
	return total;
}

int main()
{
	unsigned int x = 0;
	long start,end;
	start = GetTickCount();
	while(x++<60000){
		std::vector<int> arguments;
		arguments.push_back(100);
		arguments.push_back(200);
		arguments.push_back(300);
		int dummy = sumVector(arguments);
	}
	end = GetTickCount();
	int difVector = end - start;

	x =0;
	start = GetTickCount();
	while(x++<60000){
		int dummy = sumMacro<int>(3, 100,200,300);
	}
	end = GetTickCount();
	int difMacro = end - start ;

	x =0;
	start = GetTickCount();
	while(x++<60000){
		DynamicArray<int> arr(10);
		arr.add(100);
		arr.add(200);
		arr.add(300);
		int dummy = sumDynamicArray(arr);
	}
	end = GetTickCount();
	int difDynamicArray = end - start ;



	x =0;
	start = GetTickCount();
	while(x++<60000){
		boost::array<int,3> arr = { { 100, 200, 300} };
		arr[0] = 100;
		arr[1] = 200;
		arr[2] = 300;
		int dummy = sumBoostArray(arr);
	}
	end = GetTickCount();
	int difBoostArray = end - start ;


	cout << "It took " << difVector<< " ms , using std::vector method"<< endl;
	cout << "It took " << difMacro << " ms , using macro method"<< endl;
	cout << "It took " << difDynamicArray << " ms , using DynamicArray method"<< endl;
	cout << "It took " << difBoostArray << " ms , using BoostArray method"<< endl;
	return 0;
}

