Last active
January 30, 2016 17:19
-
-
Save jslee02/6d642d73cb0023c61243 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 <iostream> | |
#include <memory> | |
#include <typeinfo> | |
#include <typeindex> | |
#include <map> | |
#include <unordered_map> | |
template <typename T> struct type {}; | |
class Addon {}; | |
class Addon1 : public Addon {}; | |
class Derived1 : public Addon1 {}; | |
class Addon2 : public Addon {}; | |
class Derived2 : public Addon2 {}; | |
class AddonManager | |
{ | |
public: | |
using AddonMap = std::map< std::type_index, std::unique_ptr<Addon> >; | |
using SpecAddonMap = std::unordered_map< std::type_index, std::pair< std::unique_ptr<Addon>, bool> >; | |
template <class T> | |
bool isSpecializedFor() | |
{ | |
SpecAddonMap::iterator itSpec = mSpecAddonMap.find( typeid(T) ); | |
const bool foundInSpecMap = itSpec != mSpecAddonMap.end(); | |
if (foundInSpecMap) | |
return true; | |
return false; | |
} | |
template <class T> | |
bool remove() | |
{ | |
AddonMap::iterator it = mAddonMap.find( typeid(T) ); | |
const bool found = it != mAddonMap.end(); | |
if (found) | |
{ | |
mAddonMap.erase(it); | |
return true; | |
} | |
SpecAddonMap::iterator itSpec = mSpecAddonMap.find( typeid(T) ); | |
const bool foundInSpecMap = itSpec != mSpecAddonMap.end(); | |
if (foundInSpecMap && itSpec->second.second) | |
{ | |
itSpec->second.first = nullptr; | |
return true; | |
} | |
return false; | |
} | |
protected: | |
AddonMap mAddonMap; | |
SpecAddonMap mSpecAddonMap; | |
}; | |
template <class... OtherBases> | |
class AddonManagerJoiner { }; | |
template <class Base1> | |
class AddonManagerJoiner<Base1> : public Base1 { }; | |
template <class Base1, class Base2> | |
class AddonManagerJoiner<Base1, Base2> : public Base1, public Base2 | |
{ | |
public: | |
template <class T> | |
bool remove() | |
{ | |
if(Base1::template isSpecializedFor<T>()) | |
return Base1::template remove<T>(); | |
return Base2::template remove<T>(); | |
} | |
template <class T> | |
bool isSpecializedFor() | |
{ | |
return Base1::template isSpecializedFor<T>() | |
|| Base2::template isSpecializedFor<T>(); | |
} | |
}; | |
template <class... OtherSpecAddonPairs> | |
class SpecializedAddonManager { }; | |
template <class SpecAddon> | |
class SpecializedAddonManager<SpecAddon> : public virtual AddonManager | |
{ | |
public: | |
// using SpecialAddon = typename AddonPair::first_type; | |
// using OptionalityType = typename AddonPair::second_type; | |
SpecializedAddonManager() | |
{ | |
// _registerAddon(OptionalityType()); | |
using SpecAddonMapKeyT = std::pair< std::unique_ptr<Addon>, bool>; | |
using SpecAddonMapT = std::pair< std::type_index, SpecAddonMapKeyT >; | |
mSpecAddonMap.insert(SpecAddonMapT(typeid( SpecAddon ), SpecAddonMapKeyT(nullptr, true))); | |
mSpecAddonIterator = mSpecAddonMap.find(typeid( SpecAddon )); | |
} | |
template <typename T> | |
bool isSpecializedFor() { return _isSpecializedFor(type<T>()); } | |
template <typename T> | |
bool _isSpecializedFor(type<T>) { return false; } | |
bool _isSpecializedFor(type<SpecAddon>) { return true; } | |
template <typename T> | |
bool isOptional() { return _isOptional(type<T>()); } | |
template <typename T> | |
bool _isOptional(type<T>) { return true; } | |
bool _isOptional(type<SpecAddon>) | |
{ | |
return mSpecAddonIterator->second.second; | |
} | |
template <class T> | |
bool remove() | |
{ | |
return _remove(type<T>()); | |
} | |
template <typename T> | |
bool _remove(type<T>) | |
{ | |
return AddonManager::remove<T>(); | |
} | |
bool _remove(type<SpecAddon>) | |
{ | |
if (mSpecAddonIterator->second.second) | |
{ | |
mSpecAddonIterator->second.first = nullptr; | |
return true; | |
} | |
return false; | |
} | |
protected: | |
AddonManager::SpecAddonMap::iterator mSpecAddonIterator; | |
}; | |
template <class SpecAddon1, class... OtherSpecAddons> | |
class SpecializedAddonManager<SpecAddon1, OtherSpecAddons...> : | |
public AddonManagerJoiner< /*virtual*/ SpecializedAddonManager<SpecAddon1>, | |
/*virtual*/ SpecializedAddonManager<OtherSpecAddons...> > { }; | |
template <class... OtherBases> | |
class MadatoryAddonSetterJoiner { }; | |
template <class Base1> | |
class MadatoryAddonSetterJoiner<Base1> : public Base1 { }; | |
template <class Base1, class Base2> | |
class MadatoryAddonSetterJoiner<Base1, Base2> : public Base1, public Base2 {}; | |
template <class... OtherMadatoryAddon> | |
class MandatoryAddonSetter { }; | |
template <class MandatoryAddon> | |
class MandatoryAddonSetter<MandatoryAddon> : public virtual AddonManager | |
{ | |
public: | |
MandatoryAddonSetter() | |
{ | |
SpecAddonMap::iterator itSpec = mSpecAddonMap.find( typeid(MandatoryAddon) ); | |
const bool foundInSpecMap = itSpec != mSpecAddonMap.end(); | |
if (foundInSpecMap) | |
itSpec->second.second = false; | |
} | |
}; | |
template <class MandatoryAddon1, class... OtherMadatoryAddons> | |
class MandatoryAddonSetter<MandatoryAddon1, OtherMadatoryAddons...> : | |
public MadatoryAddonSetterJoiner< /*virtual*/ MandatoryAddonSetter<MandatoryAddon1>, | |
/*virtual*/ MandatoryAddonSetter<OtherMadatoryAddons...> > { }; | |
class DerivedSpecializedAddonManager : public SpecializedAddonManager<std::pair<Addon1, std::true_type>> {}; | |
class JointAddon : public Addon {}; | |
class RevoluteJointAddon : public Addon {}; | |
class PrismaticJointAddon : public Addon {}; | |
class Joint : public virtual AddonManager {}; | |
class RevoluteJoint : | |
public AddonManagerJoiner< | |
Joint, | |
SpecializedAddonManager<RevoluteJointAddon>>, | |
public MandatoryAddonSetter<RevoluteJointAddon> | |
{}; | |
class PrismaticJoint : | |
public AddonManagerJoiner< | |
Joint, | |
SpecializedAddonManager<PrismaticJointAddon>>, | |
MandatoryAddonSetter<RevoluteJointAddon> | |
{}; | |
class OptionalDerivedSpecializedAddonManager : | |
public SpecializedAddonManager<Addon1> | |
{}; | |
class NotOptionalDerivedSpecializedAddonManager : | |
public SpecializedAddonManager<Addon1>, | |
public MandatoryAddonSetter<Addon1> | |
{}; | |
int main(int argc, char *argv[]) | |
{ | |
std::cout << std::endl; | |
OptionalDerivedSpecializedAddonManager optionalManager; | |
std::cout << optionalManager.isOptional<Addon1>() << std::endl; // 1 | |
std::cout << optionalManager.isOptional<Addon2>() << std::endl; // 1 | |
std::cout << optionalManager.isOptional<int>() << std::endl; // 1 | |
std::cout << optionalManager.isOptional<Derived1>() << std::endl; // 1 | |
std::cout << optionalManager.isOptional<Derived2>() << std::endl; // 1 | |
std::cout << std::endl; | |
NotOptionalDerivedSpecializedAddonManager notOptionalManager; | |
std::cout << notOptionalManager.isOptional<Addon1>() << std::endl; // 0 | |
std::cout << std::endl; | |
SpecializedAddonManager<std::pair<Addon1, std::true_type>> derived; | |
std::cout << derived.isOptional<Addon1>() << std::endl; // 1 | |
std::cout << derived.isOptional<Addon2>() << std::endl; // 1 | |
std::cout << derived.isOptional<float>() << std::endl; // 1 | |
std::cout << derived.isOptional<Derived1>() << std::endl; // 1 | |
std::cout << derived.isOptional<Derived2>() << std::endl; // 1 | |
Joint* joint = nullptr; | |
std::unique_ptr<RevoluteJoint> revJoint(new RevoluteJoint()); | |
std::unique_ptr<PrismaticJoint> priJoint(new PrismaticJoint()); | |
std::cout << std::endl; | |
// std::cout << revJoint->isSpecializedFor<JointAddon>() << std::endl; // 1 | |
std::cout << revJoint->isSpecializedFor<RevoluteJointAddon>() << std::endl; // 1 | |
std::cout << revJoint->isSpecializedFor<PrismaticJointAddon>() << std::endl; // 0 | |
std::cout << std::endl; | |
// std::cout << priJoint->isSpecializedFor<JointAddon>() << std::endl; // 1 | |
std::cout << priJoint->isSpecializedFor<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << priJoint->isSpecializedFor<PrismaticJointAddon>() << std::endl; // 1 | |
joint = static_cast<Joint*>(revJoint.get()); | |
std::cout << std::endl; | |
// std::cout << joint->isSpecializedFor<JointAddon>() << std::endl; // 0 | |
std::cout << joint->isSpecializedFor<RevoluteJointAddon>() << std::endl; // 1 | |
std::cout << joint->isSpecializedFor<PrismaticJointAddon>() << std::endl; // 0 | |
joint = static_cast<Joint*>(priJoint.get()); | |
std::cout << std::endl; | |
// std::cout << joint->isSpecializedFor<JointAddon>() << std::endl; // 0 | |
std::cout << joint->isSpecializedFor<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << joint->isSpecializedFor<PrismaticJointAddon>() << std::endl; // 1 | |
std::cout << std::endl; | |
// std::cout << revJoint->remove<JointAddon>() << std::endl; // 0 | |
std::cout << revJoint->remove<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << revJoint->remove<PrismaticJointAddon>() << std::endl; // 0 | |
std::cout << std::endl; | |
// std::cout << priJoint->remove<JointAddon>() << std::endl; // 0 | |
std::cout << priJoint->remove<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << priJoint->remove<PrismaticJointAddon>() << std::endl; // 1 | |
joint = static_cast<Joint*>(revJoint.get()); | |
std::cout << std::endl; | |
// std::cout << joint->remove<JointAddon>() << std::endl; // 0 | |
std::cout << joint->remove<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << joint->remove<PrismaticJointAddon>() << std::endl; // 0 | |
joint = static_cast<Joint*>(priJoint.get()); | |
std::cout << std::endl; | |
// std::cout << joint->remove<JointAddon>() << std::endl; // 0 | |
std::cout << joint->remove<RevoluteJointAddon>() << std::endl; // 0 | |
std::cout << joint->remove<PrismaticJointAddon>() << std::endl; // 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment