This repository has been archived by the owner on Aug 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6d1e7b2
commit 0a429d3
Showing
113 changed files
with
2,503 additions
and
732 deletions.
There are no files selected for viewing
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
|
||
// | ||
// Created by henrik on 16.05.19. | ||
// Copyright 2020 Net64 Coop Project | ||
// Licensed under GPLv3 | ||
// Refer to the LICENSE file included | ||
// | ||
|
||
#pragma once | ||
|
||
#include <memory> | ||
#include <type_traits> | ||
#include <unordered_map> | ||
|
||
|
||
template<typename TBase, typename TKey, typename TPtr = std::unique_ptr<TBase>, typename... TArgs> | ||
struct Factory | ||
{ | ||
using FactoryType = TBase* (*)(TArgs&&... args); | ||
|
||
friend TBase; | ||
|
||
protected: | ||
Factory() = default; | ||
|
||
struct Shared | ||
{ | ||
template<typename, auto, bool> | ||
friend struct RegisterConst; | ||
template<typename, bool> | ||
friend struct RegisterDyn; | ||
friend Factory; | ||
|
||
private: | ||
static std::unordered_map<TKey, FactoryType>& get_factories() | ||
{ | ||
static std::unordered_map<TKey, FactoryType> s_factories; | ||
return s_factories; | ||
} | ||
}; | ||
|
||
static const std::unordered_map<TKey, FactoryType>& get_factories() { return Shared::get_factories(); } | ||
|
||
protected: | ||
using Identifier = TKey; | ||
|
||
template<typename T, T> | ||
struct DummyUser | ||
{ | ||
}; | ||
|
||
public: | ||
template<typename, auto, bool> | ||
friend struct RegisterConst; | ||
template<typename, bool> | ||
friend struct RegisterDyn; | ||
|
||
[[nodiscard]] static TPtr make(const TKey& key, TArgs&&... args) | ||
{ | ||
static_assert(std::is_base_of_v<Factory<TBase, TKey, TPtr, TArgs...>, TBase>, | ||
"Trying to instantiate derived class of non-registry"); | ||
return TPtr{Shared::get_factories().at(key)(std::forward<TArgs>(args)...)}; | ||
} | ||
|
||
[[nodiscard]] static TPtr make(std::string_view key, TArgs&&... args) | ||
{ | ||
return make(std::string(key), std::forward<TArgs>(args)...); | ||
} | ||
|
||
struct Empty | ||
{ | ||
}; | ||
|
||
template<typename TRegistrar, auto KEY, bool INHERIT_FROM_BASE = true> | ||
struct RegisterConst : std::conditional_t<INHERIT_FROM_BASE, TBase, Empty> | ||
{ | ||
friend TRegistrar; | ||
|
||
private: | ||
using Base = std::conditional_t<INHERIT_FROM_BASE, TBase, Empty>; | ||
using Base::Base; | ||
|
||
struct Private | ||
{ | ||
friend RegisterConst; | ||
|
||
private: | ||
static bool register_class() | ||
{ | ||
Shared::get_factories()[TKey{KEY}] = [](TArgs&&... args) -> TBase* { | ||
return new TRegistrar(std::forward<TArgs>(args)...); | ||
}; | ||
return true; | ||
} | ||
}; | ||
|
||
[[maybe_unused]] inline static bool s_registered{Private::register_class()}; | ||
using ValueUser = DummyUser<const bool*, &s_registered>; | ||
}; | ||
|
||
template<typename TRegistrar, bool INHERIT_FROM_BASE = true> | ||
struct RegisterDyn : std::conditional_t<INHERIT_FROM_BASE, TBase, Empty> | ||
{ | ||
friend TRegistrar; | ||
|
||
private: | ||
using Base = std::conditional_t<INHERIT_FROM_BASE, TBase, Empty>; | ||
using Base::Base; | ||
|
||
struct Private | ||
{ | ||
friend RegisterDyn; | ||
|
||
private: | ||
static bool register_class() | ||
{ | ||
Shared::get_factories()[TKey{TRegistrar::get_key()}] = [](TArgs&&... args) -> TBase* { | ||
return new TRegistrar(std::forward<TArgs>(args)...); | ||
}; | ||
return true; | ||
} | ||
}; | ||
|
||
[[maybe_unused]] inline static bool s_registered{Private::register_class()}; | ||
using ValueUser = DummyUser<const bool*, &s_registered>; | ||
}; | ||
}; |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
|
||
// | ||
// Created by henrik on 17.11.19. | ||
// Copyright 2020 Net64 Coop Project | ||
// Licensed under GPLv3 | ||
// Refer to the LICENSE file included | ||
// | ||
|
||
#pragma once | ||
|
||
#include <type_traits> | ||
#include <typeinfo> | ||
#include <utility> | ||
|
||
|
||
template<typename... UsrArgs> | ||
struct DoubleDispatcher | ||
{ | ||
private: | ||
struct TypeIdPredicate | ||
{ | ||
template<typename Concrete, typename Base> | ||
bool check(const Base& base) | ||
{ | ||
return (typeid(base) == typeid(Concrete)); | ||
} | ||
}; | ||
|
||
struct DynamicCastPredicate | ||
{ | ||
template<typename Concrete, typename Base> | ||
bool check(const Base& base) | ||
{ | ||
return (dynamic_cast<const Concrete*>(&base) != nullptr); | ||
} | ||
}; | ||
|
||
template<typename Base, typename Concrete> | ||
struct AddQualifiers; | ||
|
||
template<typename Base, typename Concrete> | ||
struct AddQualifiers<Base*, Concrete> | ||
{ | ||
using type = Concrete*; | ||
}; | ||
template<typename Base, typename Concrete> | ||
struct AddQualifiers<Base&, Concrete> | ||
{ | ||
using type = Concrete&; | ||
}; | ||
template<typename Base, typename Concrete> | ||
struct AddQualifiers<const Base*, Concrete> | ||
{ | ||
using type = const Concrete*; | ||
}; | ||
|
||
template<typename Base, typename Concrete> | ||
struct AddQualifiers<const Base&, Concrete> | ||
{ | ||
using type = const Concrete&; | ||
}; | ||
|
||
template<typename T> | ||
static T& deref(T* v) | ||
{ | ||
return *v; | ||
} | ||
|
||
template<typename T> | ||
static T& deref(T& v) | ||
{ | ||
return v; | ||
} | ||
|
||
public: | ||
/** | ||
* Wrapper of custom_dispatch with Predicate = TypeIdPredicate | ||
* Calls Handler::on_dispatch(Type) for every type whose runtime type is Type | ||
* Rejects any type that is not explicitly specified in ConcreteTypes, even if it is a derivative of one | ||
* If you also want to receive types which inherit from a specified type, use relaxed_dispatch | ||
* See custom_dispatch for documentation of parameters | ||
*/ | ||
template<typename Handler, typename BaseType, typename... ConcreteTypes> | ||
static bool strict_dispatch(Handler handler, BaseType param, UsrArgs... args) | ||
{ | ||
return double_dispatch<Handler, TypeIdPredicate, BaseType, ConcreteTypes...>( | ||
handler, param, TypeIdPredicate(), std::forward<UsrArgs>(args)...); | ||
} | ||
|
||
/** | ||
* Wrapper of custom_dispatch with Predicate = DynamicCastPredicate | ||
* Calls Handler::on_dispatch(Type) for every type whose runtime type is Type or a derivative of Type | ||
* See custom_dispatch for documentation of parameters | ||
*/ | ||
template<typename Handler, typename BaseType, typename... ConcreteTypes> | ||
static bool relaxed_dispatch(Handler handler, BaseType param, UsrArgs... args) | ||
{ | ||
return double_dispatch<Handler, DynamicCastPredicate, BaseType, ConcreteTypes...>( | ||
handler, param, DynamicCastPredicate(), std::forward<UsrArgs>(args)...); | ||
} | ||
|
||
/** | ||
* Calls Handler::on_dispatch(Type) with the correct concrete type of param | ||
* @tparam Handler Type to call the concrete methods on | ||
* @tparam Predicate Functor with bool check<ConcreteType>(BaseType) method to determine if BaseType can be casted | ||
* to ConcreteType | ||
* @tparam BaseType Base of all dispatched types. This type should be fully qualified (e.g. const, pointer / | ||
* reference) | ||
* @tparam ConcreteTypes List of all types a concrete function is provided for. These should not be qualified | ||
* @param handler Object to call concrete methods on | ||
* @param param Base object to dispatch | ||
* @param pred Functor of type Predicate | ||
* @return True if a matching concrete function for the runtime type of param was found | ||
*/ | ||
template<typename Handler, typename Predicate, typename BaseType, typename... ConcreteTypes> | ||
static bool custom_dispatch(Handler handler, BaseType param, Predicate pred, UsrArgs... args) | ||
{ | ||
return double_dispatch<Handler, Predicate, BaseType, ConcreteTypes...>( | ||
handler, param, pred, std::forward<UsrArgs>(args)...); | ||
} | ||
|
||
private: | ||
template<typename Handler, typename Predicate, typename BaseType, typename DerivedType, typename... DerivedTypes> | ||
static bool double_dispatch(Handler handler, BaseType param, Predicate pred, UsrArgs... args) | ||
{ | ||
if(pred.template check<DerivedType>(deref(param))) | ||
{ | ||
handler.on_dispatch(static_cast<typename AddQualifiers<BaseType, DerivedType>::type>(param), | ||
std::forward<UsrArgs>(args)...); | ||
return true; | ||
} | ||
return double_dispatch<Handler, Predicate, BaseType, DerivedTypes...>( | ||
handler, param, pred, std::forward<UsrArgs>(args)...); | ||
} | ||
|
||
template<typename Handler, typename Predicate, typename BaseType> | ||
static bool double_dispatch(Handler, BaseType, Predicate, UsrArgs...) | ||
{ | ||
return false; | ||
} | ||
}; |
Oops, something went wrong.