একটি মন্তব্য:
আর্টেমিস বাস্তবায়ন আকর্ষণীয়। আমি আমার উপাদানগুলিকে "অ্যাট্রিবিউটস" এবং "আচরণ" বলি ব্যতীত আমি অনুরূপ সমাধান নিয়ে এসেছি। ধরণের উপাদান পৃথক করার এই পদ্ধতিটি আমার পক্ষে খুব সুন্দরভাবে কাজ করেছে।
সমাধান সম্পর্কিত:
কোডটি ব্যবহার করা সহজ, তবে আপনি সি ++ এর সাথে অভিজ্ঞ না হলে বাস্তবায়নটি অনুসরণ করা শক্ত হতে পারে। তাই ...
পছন্দসই ইন্টারফেস
আমি যা করেছি তা হ'ল সমস্ত উপাদানগুলির একটি কেন্দ্রীয় ভান্ডার। প্রতিটি উপাদান টাইপ একটি নির্দিষ্ট স্ট্রিং ম্যাপ করা হয় (যা উপাদান নাম প্রতিনিধিত্ব করে)। আপনি সিস্টেমটি এভাবে ব্যবহার করেন:
// Every time you write a new component class you have to register it.
// For that you use the `COMPONENT_REGISTER` macro.
class RenderingComponent : public Component
{
// Bla, bla
};
COMPONENT_REGISTER(RenderingComponent, "RenderingComponent")
int main()
{
// To then create an instance of a registered component all you have
// to do is call the `create` function like so...
Component* comp = component::create("RenderingComponent");
// I found that if you have a special `create` function that returns a
// pointer, it's best to have a corresponding `destroy` function
// instead of using `delete` directly.
component::destroy(comp);
}
রুপায়ণ
বাস্তবায়নটি খুব খারাপ নয়, তবে এটি এখনও বেশ জটিল; এটিতে টেমপ্লেট এবং ফাংশন পয়েন্টারগুলির কিছু জ্ঞান প্রয়োজন।
দ্রষ্টব্য: জো র্রেছনিগ মন্তব্যগুলিতে কিছু ভাল পয়েন্ট তৈরি করেছেন, মূলত আমার পূর্ববর্তী বাস্তবায়নটি কোডটি অনুকূলকরণের ক্ষেত্রে সংকলকটি কতটা ভাল তা সম্পর্কে অনেক বেশি অনুমান করেছিল; ইস্যুটি ক্ষতিকারক ছিল না, তবে এটি আমাকে ত্রুটিযুক্ত করেছিল। আমি আরও লক্ষ্য করেছি যে প্রাক্তন COMPONENT_REGISTER
ম্যাক্রো টেমপ্লেটগুলির সাথে কাজ করে না।
আমি কোডটি পরিবর্তন করেছি এবং এখন এই সমস্ত সমস্যার সমাধান করা উচিত। ম্যাক্রো টেমপ্লেটগুলির সাথে কাজ করে এবং জো উত্থাপিত সমস্যাগুলি মোকাবেলা করেছে: অপ্রয়োজনীয় কোডটিকে অপ্টিমাইজ করা এখন কম্পাইলারদের পক্ষে অনেক সহজ।
কম্পোনেন্ট / component.h
#ifndef COMPONENT_COMPONENT_H
#define COMPONENT_COMPONENT_H
// Standard libraries
#include <string>
// Custom libraries
#include "detail.h"
class Component
{
// ...
};
namespace component
{
Component* create(const std::string& name);
void destroy(const Component* comp);
}
#define COMPONENT_REGISTER(TYPE, NAME) \
namespace component { \
namespace detail { \
namespace \
{ \
template<class T> \
class ComponentRegistration; \
\
template<> \
class ComponentRegistration<TYPE> \
{ \
static const ::component::detail::RegistryEntry<TYPE>& reg; \
}; \
\
const ::component::detail::RegistryEntry<TYPE>& \
ComponentRegistration<TYPE>::reg = \
::component::detail::RegistryEntry<TYPE>::Instance(NAME); \
}}}
#endif // COMPONENT_COMPONENT_H
কম্পোনেন্ট / detail.h
#ifndef COMPONENT_DETAIL_H
#define COMPONENT_DETAIL_H
// Standard libraries
#include <map>
#include <string>
#include <utility>
class Component;
namespace component
{
namespace detail
{
typedef Component* (*CreateComponentFunc)();
typedef std::map<std::string, CreateComponentFunc> ComponentRegistry;
inline ComponentRegistry& getComponentRegistry()
{
static ComponentRegistry reg;
return reg;
}
template<class T>
Component* createComponent() {
return new T;
}
template<class T>
struct RegistryEntry
{
public:
static RegistryEntry<T>& Instance(const std::string& name)
{
// Because I use a singleton here, even though `COMPONENT_REGISTER`
// is expanded in multiple translation units, the constructor
// will only be executed once. Only this cheap `Instance` function
// (which most likely gets inlined) is executed multiple times.
static RegistryEntry<T> inst(name);
return inst;
}
private:
RegistryEntry(const std::string& name)
{
ComponentRegistry& reg = getComponentRegistry();
CreateComponentFunc func = createComponent<T>;
std::pair<ComponentRegistry::iterator, bool> ret =
reg.insert(ComponentRegistry::value_type(name, func));
if (ret.second == false) {
// This means there already is a component registered to
// this name. You should handle this error as you see fit.
}
}
RegistryEntry(const RegistryEntry<T>&) = delete; // C++11 feature
RegistryEntry& operator=(const RegistryEntry<T>&) = delete;
};
} // namespace detail
} // namespace component
#endif // COMPONENT_DETAIL_H
কম্পোনেন্ট / component.cpp
// Matching header
#include "component.h"
// Standard libraries
#include <string>
// Custom libraries
#include "detail.h"
Component* component::create(const std::string& name)
{
detail::ComponentRegistry& reg = detail::getComponentRegistry();
detail::ComponentRegistry::iterator it = reg.find(name);
if (it == reg.end()) {
// This happens when there is no component registered to this
// name. Here I return a null pointer, but you can handle this
// error differently if it suits you better.
return nullptr;
}
detail::CreateComponentFunc func = it->second;
return func();
}
void component::destroy(const Component* comp)
{
delete comp;
}
লুয়ার সাথে প্রসারিত হচ্ছে
আমার অবশ্যই লক্ষ্য করা উচিত যে কিছুটা কাজের সাথে (এটি খুব বেশি কঠিন নয়), এটি কখনও চিন্তা না করেই সি ++ বা লুয়া উভয় ক্ষেত্রেই সংজ্ঞায়িত উপাদানগুলির সাথে নির্বিঘ্নে কাজ করতে ব্যবহার করা যেতে পারে।