#define _SCL_SECURE_NO_WARNINGS

#include <memory>
#include <utility>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <type_traits>
#include <ctime>
#include <cstdlib>

// std::move not included in current CTP, so cheating a little bit
namespace std
{
  template <typename T>
  inline typename tr1::remove_reference<T>::type&&
      move(T&& t)
  {
    return t;
  }
}

#define USE_CPP0X_MOVE_SEMANTICS
//#define TRACE_CONSTRUCT_DESTRUCT

template <typename T>
class fixed_vector
{
  T* buf_;
  size_t size_;
public:
  fixed_vector() : buf_(0), size_(0)
  {
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: constructor\n";
#endif
  }

  fixed_vector(size_t size)
    : buf_(new T[size]), size_(size)
  {
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: size constructor\n";
#endif
  }

  fixed_vector(const fixed_vector& other)
    : buf_(new T[other.size_]), size_(other.size_)
  {
    std::copy(other.buf_, other.buf_ + other.size_, buf_);
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: copy constructor\n";
#endif
  }

#ifdef USE_CPP0X_MOVE_SEMANTICS
  fixed_vector(fixed_vector&& other)
    : buf_(other.buf_), size_(other.size_)
  {
    other.buf_ = 0;
    other.size_ = 0;
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: move constructor\n";
#endif
  }

  fixed_vector& operator=(fixed_vector&& other)
  {
    std::swap(buf_, other.buf_);
    std::swap(size_, other.size_);
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: assignment operator\n";
#endif
    return *this;
  }
#endif

  ~fixed_vector()
  {
#ifdef TRACE_CONSTRUCT_DESTRUCT
    std::cout << "fixed_vector: destructor, buf_=" << buf_ << "\n";
#endif
    delete buf_;
  }

  void swap(fixed_vector& other)
  {
    std::swap(buf_, other.buf_);
    std::swap(size_, other.size_);
  }
};

template <size_t RecurCalls>
struct recur_val
{
  static fixed_vector<int> invoke(size_t elems)
  {
    fixed_vector<int> mt(recur_val<RecurCalls-1>::invoke(elems));
    return mt; // Avoids RVO
  }
};

template <>
struct recur_val<0>
{
  static fixed_vector<int> invoke(size_t elems)
  {
    fixed_vector<int> mt(elems);
    return mt;
  }
};

template <size_t RecurCalls>
struct recur_ptr
{
  static std::auto_ptr<fixed_vector<int>> invoke(size_t elems)
  {
    std::auto_ptr<fixed_vector<int>> mt(
        recur_ptr<RecurCalls-1>::invoke(elems));
    return mt; // Avoids RVO
  }
};

template <>
struct recur_ptr<0>
{
  static std::auto_ptr<fixed_vector<int>> invoke(size_t elems)
  {
    std::auto_ptr<fixed_vector<int>> mt(
        new fixed_vector<int>(elems));
    return mt;
  }
};

template <typename T, typename Recurser>
void time_it()
{
  int iters = 100;
  std::clock_t total = 0;
  for (int i = 0; i < iters; ++i)
  {
    std::clock_t start = std::clock();
    for (int j = 0; j < 1000; ++j)
    {
      T v1 = Recurser::invoke(4096 + rand() % 4096);
    }
    std::clock_t end = std::clock();
    total += end - start;  // Might cause some timing errors
    std::cout << ".";
  }

  std::cout << "\n";
  std::cout << total / static_cast<double>(CLOCKS_PER_SEC) << "s total\n";
  std::cout << (total / iters) / static_cast<double>(CLOCKS_PER_SEC) << " s average\n";
}

int main(int argc, char* argv[])
{
  srand(static_cast<unsigned int>(time(NULL)));
  std::cout << "Timing return by value...\n";
#ifdef USE_CPP0X_MOVE_SEMANTICS
  std::cout << "Using C++0x move semantics\n";
#endif
  time_it<fixed_vector<int>, recur_val<5>>();
  std::cout << "Timing return by auto_ptr...\n";
  time_it<std::auto_ptr<fixed_vector<int>>, recur_ptr<5>>();
  std::string temp;
  std::getline(std::cin, temp);

  return 0;
}


