Skip to content

Commit

Permalink
Port to MSVC 2013.
Browse files Browse the repository at this point in the history
Conflicts:
	include/yorel/methods/extern_macros.hpp
	include/yorel/methods/macros.hpp
	include/yorel/multi_methods/detail.hpp
	include/yorel/multi_methods/no_macros.hpp
	src/multi_methods.cpp
	tests/tests.cpp
  • Loading branch information
jll63 committed Mar 28, 2015
1 parent 1c8cd0e commit 12ed18b
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 80 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -30,3 +30,6 @@ Makefile
/examples/libdl_shared.so
/install_manifest.txt
/doc/multi_methods.xml
/build
*.sdf
*.suo
4 changes: 4 additions & 0 deletions CMakeLists.txt
Expand Up @@ -26,6 +26,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "-std=c++11")
endif()

if(MSVC)
set(CMAKE_CXX_FLAGS "-D_SCL_SECURE_NO_WARNINGS /EHsc")
endif()

add_subdirectory (src)
add_subdirectory (tests)
add_subdirectory (examples)
Expand Down
1 change: 1 addition & 0 deletions examples/asteroids.cpp
Expand Up @@ -9,6 +9,7 @@
#include <yorel/multi_methods.hpp>

#include <iostream>
#include <string>

using namespace std;
using yorel::multi_methods::virtual_;
Expand Down
7 changes: 6 additions & 1 deletion include/yorel/multi_methods/detail.hpp
Expand Up @@ -212,6 +212,11 @@ struct init_ptr<> {
}
};

template<typename SIG>
struct signature {
using type = SIG;
};

template<>
struct get_mm_table<false> {
using class_of_type = std::unordered_map<std::type_index, const std::vector<mm_class::offset>*>;
Expand Down Expand Up @@ -322,7 +327,7 @@ struct multi_method_implementation : multi_method_base {
template<typename R, typename... P>
template<class M>
method_base* multi_method_implementation<R, P...>::add_spec() {
using method_signature = decltype(M::body);
using method_signature = typename M::body_signature::type;
using target = typename wrapper<M, method_signature, signature>::type;
using method_virtuals = typename extract_method_virtuals<R(P...), method_signature>::type;

Expand Down
31 changes: 16 additions & 15 deletions include/yorel/multi_methods/macros.hpp
Expand Up @@ -7,40 +7,41 @@
// http://www.boost.org/LICENSE_1_0.txt)

#undef MM_CLASS
#define MM_CLASS(CLASS, BASES...) \
using _yomm11_base_list = ::yorel::multi_methods::mm_class::base_list<BASES>; \
virtual void _yomm11_init_class_() { &::yorel::multi_methods::mm_class::initializer<CLASS, ::yorel::multi_methods::mm_class::base_list<BASES>>::the; }
#define MM_CLASS(CLASS, ...) \
using _yomm11_base_list = ::yorel::multi_methods::mm_class::base_list<__VA_ARGS__>; \
virtual void _yomm11_init_class_() { &::yorel::multi_methods::mm_class::initializer<CLASS, ::yorel::multi_methods::mm_class::base_list<__VA_ARGS__>>::the; }

#undef MM_EXTERN_CLASS
#define MM_EXTERN_CLASS(CLASS)

#define MM_FOREIGN_CLASS(CLASS, BASES...) \
static_assert(::yorel::multi_methods::detail::check_bases<CLASS, ::yorel::multi_methods::mm_class::base_list<BASES>>::value, "error in MM_FOREIGN_CLASS(): not a base in base list"); \
#define MM_FOREIGN_CLASS(CLASS, ...) \
static_assert(::yorel::multi_methods::detail::check_bases<CLASS, ::yorel::multi_methods::mm_class::base_list<__VA_ARGS__>>::value, "error in MM_FOREIGN_CLASS(): not a base in base list"); \
static_assert(std::is_polymorphic<CLASS>::value, "error: class must be polymorphic"); \
namespace { ::yorel::multi_methods::mm_class::initializer<CLASS, ::yorel::multi_methods::mm_class::base_list<BASES>> _yomm11_add_class_ ## CLASS; }
namespace { ::yorel::multi_methods::mm_class::initializer<CLASS, ::yorel::multi_methods::mm_class::base_list<__VA_ARGS__>> _yomm11_add_class_ ## CLASS; }

#define MM_INIT() \
::yorel::multi_methods::detail::init_ptr<_yomm11_base_list>::init(this)

#undef MM_CLASS_MULTI
#define MM_CLASS_MULTI(CLASS, BASE, BASES...) \
MM_CLASS(CLASS, BASE, BASES); \
#define MM_CLASS_MULTI(CLASS, BASE, ...) \
MM_CLASS(CLASS, BASE, __VA_ARGS__); \
std::vector<mm_class::offset>* _get_yomm11_ptbl() const { return BASE::_yomm11_ptbl; }

#define MM_INIT_MULTI(BASE) \
this->BASE::_init_yomm11_ptr(this)

#undef MULTI_METHOD
#define MULTI_METHOD(ID, RETURN_TYPE, ARGS...) \
#define MULTI_METHOD(ID, RETURN_TYPE, ...) \
template<typename Sig> struct ID ## _specialization; \
constexpr ::yorel::multi_methods::multi_method<ID ## _specialization, RETURN_TYPE(ARGS)> ID{}
const ::yorel::multi_methods::multi_method<ID ## _specialization, RETURN_TYPE(__VA_ARGS__)> ID

#define BEGIN_SPECIALIZATION(ID, RESULT, ARGS...) \
#define BEGIN_SPECIALIZATION(ID, RESULT, ...) \
template<> \
struct ID ## _specialization<RESULT(ARGS)> : decltype(ID)::specialization<ID ## _specialization<RESULT(ARGS)>> { \
virtual void* _yomm11_install() { return &decltype(ID)::register_spec<ID ## _specialization>::the; } \
static RESULT body(ARGS) {
struct ID ## _specialization<RESULT(__VA_ARGS__)> : std::remove_const<decltype(ID)>::type::specialization< ID ## _specialization<RESULT(__VA_ARGS__)> > { \
virtual void* _yomm11_install() { return &::yorel::multi_methods::register_spec<decltype(ID), ID ## _specialization>::the; } \
using body_signature = ::yorel::multi_methods::detail::signature<RESULT(__VA_ARGS__)>; \
static RESULT body(__VA_ARGS__) {

#define END_SPECIALIZATION } };

#define GET_SPECIALIZATION(ID, RESULT, ARGS...) ID ## _specialization<RESULT(ARGS)>::body
#define GET_SPECIALIZATION(ID, RESULT, ...) ID ## _specialization<RESULT(__VA_ARGS__)>::body
61 changes: 33 additions & 28 deletions include/yorel/multi_methods/no_macros.hpp
Expand Up @@ -9,6 +9,16 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// Copied from Boost.
#ifdef _MSVC_VER
#pragma warning( push )
#pragma warning( disable: 4250 )
#pragma warning( disable: 4284 )
#pragma warning( disable: 4996 )
#elif defined(__GNUC__) && (__GNUC__ >= 4)
#pragma GCC system_header
#endif

#include <typeinfo>
#include <typeindex>
#include <type_traits>
Expand All @@ -30,14 +40,6 @@
#define YOREL_MM_TRACE(e)
#endif

// Copied from Boost.
#ifdef _MSVC_VER
#pragma warning( push )
#pragma warning( disable : 4584 4250)
#elif defined(__GNUC__) && (__GNUC__ >= 4)
#pragma GCC system_header
#endif

namespace yorel {
namespace multi_methods {

Expand Down Expand Up @@ -79,7 +81,7 @@ class bitvec {
ref(word* p, int i) : p(p), i(i) {
}
operator bool() const {
return p[i / bpw] & (1 << (i % bpw));
return (p[i / bpw] & (1 << (i % bpw))) != 0;
}
ref& operator =(bool val) {
if (val) {
Expand Down Expand Up @@ -147,7 +149,7 @@ class bitvec {
}

bool operator [](int i) const {
return p[i / bpw] & (1 << (i % bpw));
return (p[i / bpw] & (1 << (i % bpw))) != 0;
}

ref operator [](int i) { return ref(p, i); }
Expand Down Expand Up @@ -254,7 +256,7 @@ struct mm_class {
std::vector<mmref> rooted_here; // multi_methods rooted here for one or more args.
bool abstract;

static std::unique_ptr<std::unordered_set<mm_class*>> to_initialize;
static std::unordered_set<mm_class*>* to_initialize;
static void add_to_initialize(mm_class* pc);
static void remove_from_initialize(mm_class* pc);

Expand Down Expand Up @@ -349,7 +351,7 @@ struct multi_method_base {
std::vector<method_base*> methods;
std::vector<int> steps;

static std::unique_ptr<std::unordered_set<multi_method_base*>> to_initialize;
static std::unordered_set<multi_method_base*>* to_initialize;
static void add_to_initialize(multi_method_base* pm);
static void remove_from_initialize(multi_method_base* pm);
};
Expand Down Expand Up @@ -407,22 +409,14 @@ struct multi_method<Method, R(P...)> {

using implementation = detail::multi_method_implementation<R, P...>;
static implementation& the();
static std::unique_ptr<implementation> impl;
static implementation* impl;

template<class Spec>
static bool specialize() {
the().template add_spec<Spec>();
return true;
}

template<class Spec>
struct register_spec {
register_spec() {
specialize<Spec>();
}
static register_spec the;
};

template<class Spec>
struct specialization {
static method_pointer_type next;
Expand All @@ -431,18 +425,26 @@ struct multi_method<Method, R(P...)> {
};
};

template<class Method, class Spec>
struct register_spec {
register_spec() {
Method::template specialize<Spec>();

}
static register_spec the;

};

template<class Method, class Spec>
register_spec<Method, Spec> register_spec<Method, Spec>::the;

template<template<typename Sig> class Method, typename R, typename... P>
template<class Spec>
typename multi_method<Method, R(P...)>::method_pointer_type
multi_method<Method, R(P...)>::specialization<Spec>::next;

template<template<typename Sig> class Method, typename R, typename... P>
template<class Spec>
multi_method<Method, R(P...)>::register_spec<Spec>
multi_method<Method, R(P...)>::register_spec<Spec>::the;

template<template<typename Sig> class Method, typename R, typename... P>
std::unique_ptr<typename multi_method<Method, R(P...)>::implementation> multi_method<Method, R(P...)>::impl;
typename multi_method<Method, R(P...)>::implementation* multi_method<Method, R(P...)>::impl;

template<template<typename Sig> class Method, typename R, typename... P>
template<typename Tag>
Expand All @@ -451,7 +453,7 @@ typename multi_method<Method, R(P...)>::method_pointer_type multi_method<Method,
template<template<typename Sig> class Method, typename R, typename... P>
typename multi_method<Method, R(P...)>::implementation& multi_method<Method, R(P...)>::the() {
if (!impl) {
impl.reset(new implementation);
impl = new implementation;
}

return *impl;
Expand All @@ -471,4 +473,7 @@ inline R multi_method<Method, R(P...)>::method(typename detail::remove_virtual<P
}
}

#ifdef _MSVC_VER
#pragma warning( pop )
#endif
#endif
30 changes: 16 additions & 14 deletions src/multi_methods.cpp
Expand Up @@ -9,6 +9,7 @@
#include <yorel/multi_methods.hpp>
#include <yorel/multi_methods/runtime.hpp>
#include <unordered_set>
#include <iterator>
#include <functional>
#include <cassert>

Expand Down Expand Up @@ -119,13 +120,12 @@ void mm_class::initialize(const vector<mm_class*>& b) {
});
}

unique_ptr<unordered_set<mm_class*>> mm_class::to_initialize;

unordered_set<mm_class*>* mm_class::to_initialize;
void mm_class::add_to_initialize(mm_class* pc) {
YOREL_MM_TRACE(cout << "add to initialize: " << pc << endl);

if (!to_initialize) {
to_initialize.reset(new unordered_set<mm_class*>);
to_initialize = new unordered_set<mm_class*>;
}

to_initialize->insert(pc);
Expand All @@ -138,7 +138,8 @@ void mm_class::remove_from_initialize(mm_class* pc) {
to_initialize->erase(pc);

if (to_initialize->empty()) {
to_initialize.reset();
delete to_initialize;
to_initialize = nullptr;
}
}
}
Expand Down Expand Up @@ -247,11 +248,11 @@ void hierarchy_initializer::assign_slots() {
void initialize() {
while (mm_class::to_initialize) {
auto pc = *mm_class::to_initialize->begin();
if (pc->is_root()) {
hierarchy_initializer::initialize(*pc);
} else {
mm_class::remove_from_initialize(pc);
}
if (pc->is_root()) {
hierarchy_initializer::initialize(*pc);
} else {
mm_class::remove_from_initialize(pc);
}
}

while (multi_method_base::to_initialize) {
Expand All @@ -272,7 +273,7 @@ bool method_base::specializes(method_base* other) const {

bool result = false;

for (int dim = 0; dim < args.size(); dim++) {
for (size_t dim = 0; dim < args.size(); dim++) {
if (args[dim] != other->args[dim]) {
if (args[dim]->specializes(*other->args[dim])) {
result = true;
Expand Down Expand Up @@ -344,11 +345,11 @@ void multi_method_base::invalidate() {
add_to_initialize(this);
}

unique_ptr<unordered_set<multi_method_base*>> multi_method_base::to_initialize;
unordered_set<multi_method_base*>* multi_method_base::to_initialize;

void multi_method_base::add_to_initialize(multi_method_base* pm) {
if (!to_initialize) {
to_initialize.reset(new unordered_set<multi_method_base*>);
to_initialize = new unordered_set<multi_method_base*>;
}

to_initialize->insert(pm);
Expand All @@ -359,7 +360,8 @@ void multi_method_base::remove_from_initialize(multi_method_base* pm) {
to_initialize->erase(pm);

if (to_initialize->empty()) {
to_initialize.reset();
delete to_initialize;
to_initialize = nullptr;
}
}
}
Expand Down Expand Up @@ -484,7 +486,7 @@ method_base* grouping_resolver::find_best(const vector<method_base*>& candidates
while (best_iter != best.end()) {
if (method->specializes(*best_iter)) {
YOREL_MM_TRACE(cout << method << " specializes " << *best_iter << ", removed\n");
best.erase(best_iter);
best_iter = best.erase(best_iter);
} else if ((*best_iter)->specializes(method)) {
YOREL_MM_TRACE(cout << *best_iter << " specializes " << method << ", removed\n");
best_iter = best.end();
Expand Down

0 comments on commit 12ed18b

Please sign in to comment.