Created
June 4, 2016 06:35
-
-
Save svgpp/b55bd8e8f760b207d3dedd5a5e5427b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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