Skip to content

Instantly share code, notes, and snippets.

@svgpp
Created June 4, 2016 06:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svgpp/b55bd8e8f760b207d3dedd5a5e5427b3 to your computer and use it in GitHub Desktop.
Save svgpp/b55bd8e8f760b207d3dedd5a5e5427b3 to your computer and use it in GitHub Desktop.
#include "stdafx.h"
#include <assert.h>
#include <new>
#include <typeinfo>
#include <Windows.h>
#include <iostream>
struct Intf
{
virtual void copy(const void * source, void * destination) const = 0;
virtual void move(void * source, void * destination) const = 0;
virtual void destroy(void * object) const = 0;
virtual std::size_t get_size() const = 0;
virtual const std::type_info * get_type() const = 0;
};
template<class T>
struct Impl: Intf
{
void copy(const void * source, void * destination) const override
{
new (destination) T(*static_cast<const T *>(source));
}
void move(void * source, void * destination) const override
{
new (destination) T(std::move(*static_cast<T *>(source)));
}
void destroy(void * object) const override
{
static_cast<T *>(object)->~T();
}
std::size_t get_size() const override { return sizeof(T); }
const std::type_info * get_type() const override { return std::addressof(typeid(T)); }
};
template <typename T>
auto copy(const void * source, void * destination)
{
new (destination) T(*static_cast<const T *>(source));
}
template <typename T>
void move(void * source, void * destination)
{
new (destination) T(std::move(*static_cast<T *>(source)));
}
template <typename T>
void destroy(void * object)
{
static_cast<T *>(object)->~T();
}
enum struct operation_t
{
copy,
move,
destroy,
size,
type
};
using manager_t = void(*) (operation_t, const void *, void *);
template <typename T>
void manage(operation_t todo, const void * source, void * destination)
{
switch (todo)
{
case operation_t::copy:
{
copy<T>(source, destination);
break;
}
case operation_t::move:
{
move<T>(const_cast<void *>(source), destination);
break;
}
case operation_t::destroy:
{
assert(source == nullptr);
destroy<T>(destination);
break;
}
case operation_t::size:
{
assert(source == nullptr);
*static_cast<std::size_t *>(destination) = sizeof(T);
break;
}
case operation_t::type:
{
assert(source == nullptr);
*static_cast<const std::type_info **>(destination) = std::addressof(typeid(T));
break;
}
}
}
int main()
{
volatile manager_t m = &manage<int>;
const Impl<int> impl;
const Intf * volatile intf = &impl;
const int nCycles = 1000000000;
int buf1[100], buf2[100];
for(int step = 0; step < 2; ++step)
{
{
auto t1 = ::GetTickCount();
for(int i=0; i<nCycles; ++i)
{
intf->copy(&buf1, &buf2);
intf->move(&buf1, &buf2);
intf->destroy(&buf1);
auto n = intf->get_size();
auto t = intf->get_type();
}
auto t2 = ::GetTickCount();
if (step == 1)
std::cout << "Virtual: " << (t2-t1) << std::endl;
}
{
auto t1 = ::GetTickCount();
for (int i = 0; i<nCycles; ++i)
{
m(operation_t::copy, &buf1, &buf2);
m(operation_t::move, &buf1, &buf2);
m(operation_t::destroy, nullptr, &buf1);
std::size_t s;
m(operation_t::size, nullptr, &s);
const std::type_info * t;
m(operation_t::type, nullptr, &t);
}
auto t2 = ::GetTickCount();
if (step == 1)
std::cout << "Direct: " << (t2 - t1) << std::endl;
}
}
char c;
std::cin >> c;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment