c++ - উনল - সি++ বই




আমি কিভাবে একটি সি++ অ্যাপ্লিকেশন প্রতিফলন যোগ করতে পারেন? (20)

আমি একটি C ++ ক্লাসের নাম, বিষয়বস্তু (অর্থাত্ সদস্যদের এবং তাদের প্রকার) ইত্যাদির জন্য স্বতঃস্ফূর্ত করতে চাই। আমি এখানে স্থানীয় C ++ কথা বলছি, সি ++ পরিচালিত নয়, যা প্রতিফলন করেছে। আমি বুঝতে পারি সি ++ RTTI ব্যবহার করে কিছু সীমিত তথ্য সরবরাহ করে। কোন অতিরিক্ত লাইব্রেরি (বা অন্যান্য কৌশল) এই তথ্য সরবরাহ করতে পারে?


RTTI সি ++ জন্য বিদ্যমান নেই।

এই সহজভাবে ভুল। প্রকৃতপক্ষে, "RTTI" শব্দটি সি ++ মান অনুসারে তৈরি করা হয়েছিল। অন্য দিকে, আরটিটিআই প্রতিফলন বাস্তবায়নে খুব দূরে যায় না।


C ++ এ প্রতিফলন খুবই দরকারী, ক্ষেত্রে আপনি প্রতিটি সদস্যের জন্য কিছু পদ্ধতি চালানোর প্রয়োজন হয় (উদাহরণস্বরূপ: সিরিয়ালাইজেশন, হ্যাশিং, তুলনা)। আমি সাধারণ সমাধান সঙ্গে এসেছিলেন, খুব সহজ সিনট্যাক্স সঙ্গে:

struct S1
{
    ENUMERATE_MEMBERS(str,i);
    std::string str;
    int i;
};
struct S2
{
    ENUMERATE_MEMBERS(s1,i2);
    S1 s1;
    int i2;
};

ENUMERATE_MEMBERS একটি ম্যাক্রো যেখানে, পরে বর্ণিত হয় (আপডেট):

অনুমান করুন আমরা int এবং std :: স্ট্রিং এর জন্য সিরিয়ালাইজেশন ফাংশন সংজ্ঞায়িত করেছি:

void EnumerateWith(BinaryWriter & writer, int val)
{
    //store integer
    writer.WriteBuffer(&val, sizeof(int));
}
void EnumerateWith(BinaryWriter & writer, std::string val)
{
    //store string
    writer.WriteBuffer(val.c_str(), val.size());
}

এবং আমাদের "গোপন ম্যাক্রো" এর কাছাকাছি জেনেরিক ফাংশন আছে;)

template<typename TWriter, typename T>
auto EnumerateWith(TWriter && writer, T && val) -> is_enumerable_t<T>
{
    val.EnumerateWith(write); //method generated by ENUMERATE_MEMBERS macro
}

এখন আপনি লিখতে পারেন

S1 s1;
S2 s2;
//....
BinaryWriter writer("serialized.bin");

EnumerateWith(writer, s1); //this will call EnumerateWith for all members of S1
EnumerateWith(writer, s2); //this will call EnumerateWith for all members of S2 and S2::s1 (recursively)

সুতরাং স্ট্রাইক সংজ্ঞাতে ENUMERATE_MEMBERS ম্যাক্রো থাকা, আপনি মূল ধরণের স্পর্শ না করে সিরিয়ালাইজেশন, তুলনা, হ্যাশিং এবং অন্যান্য উপাদানগুলি তৈরি করতে পারেন, শুধুমাত্র প্রতিটি প্রয়োজনের জন্য "সংখ্যাসূচক পদ্ধতি" পদ্ধতি বাস্তবায়ন করতে হবে, যা সংখ্যাসূচক নয়, প্রতি সংখ্যাবহুল (বাইনারিওয়াইডারের মতো) । সাধারণত আপনার প্রোজেক্টের যেকোনো প্রকারকে সমর্থন করার জন্য আপনাকে 10-20 "সাধারণ" প্রকারগুলি প্রয়োগ করতে হবে।

এই ম্যাক্রোতে রান-টাইম নির্মাণ / ধ্বংসের শূন্য ওভারহেড থাকা উচিত এবং T.EnumerateWith () এর কোডটি অন-ডিমের জেনারেট করা উচিত, যা এটি টেমপ্লেট-ইনলাইন ফাংশন তৈরি করে অর্জন করা যেতে পারে, যাতে শুধুমাত্র ওভারহেড সমস্ত গল্প ENUMERATE_MEMBERS (m1, m2, m3 ...) প্রতিটি স্ট্রাক্টে যোগ করতে হয়, যখন সদস্যের নির্দিষ্ট পদ্ধতি প্রয়োগ করার পদ্ধতিটি কোনও সমাধানতে অবশ্যই আবশ্যক, তাই আমি ওভারহেড হিসাবে এটি অনুমান করি না।

আপডেট: ENUMERATE_MEMBERS ম্যাক্রোর খুব সহজ বাস্তবায়ন (তবে এটি সংখ্যাসূচক কাঠামোর থেকে উত্তরাধিকার সমর্থন করার জন্য সামান্য বর্ধিত হতে পারে)

#define ENUMERATE_MEMBERS(...) \
template<typename TEnumerator> inline void EnumerateWith(TEnumerator & enumerator) const { EnumerateWithHelper(enumerator, __VA_ARGS__ ); }\
template<typename TEnumerator> inline void EnumerateWith(TEnumerator & enumerator) { EnumerateWithHelper(enumerator, __VA_ARGS__); }

// EnumerateWithHelper
template<typename TEnumerator, typename ...T> inline void EnumerateWithHelper(TEnumerator & enumerator, T &...v) 
{ 
    int x[] = { (EnumerateWith(enumerator, v), 1)... }; 
}

// Generic EnumerateWith
template<typename TEnumerator, typename T>
auto EnumerateWith(TEnumerator & enumerator, T & val) -> std::void_t<decltype(val.EnumerateWith(enumerator))>
{
    val.EnumerateWith(enumerator);
}

এবং এই কোডের 15 টি লাইনের জন্য আপনার কোন তৃতীয় পক্ষের লাইব্রেরি দরকার নেই;)


আপনি কি করতে হবে preprocessor ক্ষেত্র সম্পর্কে প্রতিফলন তথ্য উৎপন্ন আছে। এই তথ্য নেস্টেড ক্লাস হিসাবে সংরক্ষণ করা যেতে পারে।

প্রথমত, প্রিপ্রোসেসারে এটি লিখতে সহজ এবং পরিচ্ছন্ন করতে আমরা টাইপ করা এক্সপ্রেশন ব্যবহার করব। একটি টাইপ করা অভিব্যক্তি শুধুমাত্র একটি অভিব্যক্তি যা প্রকারের বন্ধনীটি রাখে। তাই লেখার পরিবর্তে int x লিখবেন (int) x । টাইপ করা এক্সপ্রেশনগুলির সাহায্যে এখানে কিছু সহজ ম্যাক্রো রয়েছে:

#define REM(...) __VA_ARGS__
#define EAT(...)

// Retrieve the type
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
// Strip off the type
#define STRIP(x) EAT x
// Show the type without parenthesis
#define PAIR(x) REM x

পরবর্তী, আমরা প্রতিটি ক্ষেত্রের সম্পর্কে ডেটা জেনারেট করতে একটি REFLECTABLE ম্যাক্রো সংজ্ঞায়িত (প্লাস ক্ষেত্র নিজেই)। এই ম্যাক্রো এইভাবে বলা হবে:

REFLECTABLE
(
    (const char *) name,
    (int) age
)

সুতরাং Boost.PP ব্যবহার করে আমরা প্রতিটি আর্গুমেন্টের উপর পুনরাবৃত্তি করি এবং এর মতো ডেটা জেনারেট করি:

// A helper metafunction for adding const to a type
template<class M, class T>
struct make_const
{
    typedef T type;
};

template<class M, class T>
struct make_const<const M, T>
{
    typedef typename boost::add_const<T>::type type;
};


#define REFLECTABLE(...) \
static const int fields_n = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); \
friend struct reflector; \
template<int N, class Self> \
struct field_data {}; \
BOOST_PP_SEQ_FOR_EACH_I(REFLECT_EACH, data, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

#define REFLECT_EACH(r, data, i, x) \
PAIR(x); \
template<class Self> \
struct field_data<i, Self> \
{ \
    Self & self; \
    field_data(Self & self) : self(self) {} \
    \
    typename make_const<Self, TYPEOF(x)>::type & get() \
    { \
        return self.STRIP(x); \
    }\
    typename boost::add_const<TYPEOF(x)>::type & get() const \
    { \
        return self.STRIP(x); \
    }\
    const char * name() const \
    {\
        return BOOST_PP_STRINGIZE(STRIP(x)); \
    } \
}; \

এইটি কি একটি ধ্রুবক fields_n তৈরি করে যা fields_n ক্ষেত্রগুলির সংখ্যা। তারপর এটি প্রতিটি ক্ষেত্রের জন্য field_data বিশেষজ্ঞ। এটি reflector শ্রেণির reflector , এটি এমন যে এটি ব্যক্তিগত থাকলেও সেগুলি ক্ষেত্রগুলিতে অ্যাক্সেস করতে পারে:

struct reflector
{
    //Get field_data at index N
    template<int N, class T>
    static typename T::template field_data<N, T> get_field_data(T& x)
    {
        return typename T::template field_data<N, T>(x);
    }

    // Get the number of fields
    template<class T>
    struct fields
    {
        static const int n = T::fields_n;
    };
};

এখন ক্ষেত্রের উপর পুনরাবৃত্তি আমরা পরিদর্শক প্যাটার্ন ব্যবহার। আমরা 0 থেকে ক্ষেত্রের সংখ্যা থেকে একটি এমপিএল রেঞ্জ তৈরি করি এবং সেই সূচীতে ক্ষেত্রের ডেটা অ্যাক্সেস করি। তারপর ব্যবহারকারীর প্রদত্ত দর্শকের কাছে এটি ক্ষেত্রের ডেটা পাস করে:

struct field_visitor
{
    template<class C, class Visitor, class I>
    void operator()(C& c, Visitor v, I)
    {
        v(reflector::get_field_data<I::value>(c));
    }
};


template<class C, class Visitor>
void visit_each(C & c, Visitor v)
{
    typedef boost::mpl::range_c<int,0,reflector::fields<C>::n> range;
    boost::mpl::for_each<range>(boost::bind<void>(field_visitor(), boost::ref(c), v, _1));
}

এখন সত্যের মুহূর্তে আমরা একে একসঙ্গে রেখেছি। এখানে আমরা কীভাবে একটি Person শ্রেণীর সংজ্ঞা দিতে পারি যা প্রতিফলিত:

struct Person
{
    Person(const char *name, int age)
        :
        name(name),
        age(age)
    {
    }
private:
    REFLECTABLE
    (
        (const char *) name,
        (int) age
    )
};

এখানে একটি সাধারণকৃত print_fields ফাংশন ক্ষেত্রের উপর পুনরাবৃত্তি প্রতিফলন তথ্য ব্যবহার করে:

struct print_visitor
{
    template<class FieldData>
    void operator()(FieldData f)
    {
        std::cout << f.name() << "=" << f.get() << std::endl;
    }
};

template<class T>
void print_fields(T & x)
{
    visit_each(x, print_visitor());
}

print_fields Person শ্রেণীর সাথে print_fields ব্যবহার করার একটি উদাহরণ:

int main()
{
    Person p("Tom", 82);
    print_fields(p);
    return 0;
}

কোন আউটপুট:

name=Tom
age=82

এবং voila, আমরা কোডের 100 লাইনের নীচে, সি ++ এ প্রতিফলন বাস্তবায়ন করেছি।


আপনি প্রতিফলন সঙ্গে কি করার চেষ্টা করছেন?
আপনি কম্পাইল-টাইম প্রতিফলন সীমিত রূপ হিসাবে বুস্ট টাইপ বৈশিষ্ট্য এবং typeof লাইব্রেরিগুলি ব্যবহার করতে পারেন। অর্থাৎ, আপনি একটি টেমপ্লেট পাস একটি ধরনের মৌলিক বৈশিষ্ট্য পরিদর্শন এবং সংশোধন করতে পারেন।


আমি Qt ব্যবহার করে সুপারিশ করবে।

একটি ওপেন সোর্স লাইসেন্স পাশাপাশি একটি বাণিজ্যিক লাইসেন্স আছে।


আমি আমার সি ++ দিনের থেকে জানি দুটি প্রতিফলন-মত সমাধানগুলি হল:

1) RTTI ব্যবহার করুন, যা আপনার প্রতিফলন-মত আচরণ গড়ে তুলতে আপনার জন্য একটি বুটস্ট্র্যাপ সরবরাহ করবে, যদি আপনি আপনার সমস্ত ক্লাসকে একটি 'অবজেক্ট' বেস ক্লাস থেকে প্রাপ্ত করতে সক্ষম হন। সেই শ্রেণীটি GetMethod, GetBaseClass ইত্যাদি কিছু পদ্ধতি সরবরাহ করতে পারে। এই পদ্ধতিগুলি কীভাবে কাজ করে সে সম্পর্কে আপনাকে নিজের ধরণের সাজাইয়া কিছু ম্যাক্রো যুক্ত করতে হবে, যা দৃশ্যগুলি পিছনে মেটাডেটা তৈরি করে GetMethods ইত্যাদি প্রদান করে।

2) অন্য একটি বিকল্প, যদি আপনার কম্পাইলার বস্তুর অ্যাক্সেস থাকে DIA SDK ব্যবহার করা হয়। আমি সঠিকভাবে মনে রাখি এটি আপনাকে পিডিএস খুলতে দেয়, যা আপনার C ++ প্রকারের জন্য মেটাডেটা ধারণ করে। এটা আপনার প্রয়োজন কি করতে যথেষ্ট হতে পারে। এই পৃষ্ঠাটি উদাহরণস্বরূপ আপনি কোন বর্গের সমস্ত বেসিক ধরণের কীভাবে পেতে পারেন তা দেখায়।

এই উভয় সমাধান যদিও একটু কুৎসিত! C # এর বিলাসবহুলতাকে প্রশংসা করার জন্য সি ++ এর মতো কিছু নেই।

গুড লাক।


আমি মনে করি আপনি ডমিনিক ফিলিয়ন দ্বারা "C ++ প্রতিফলনের জন্য টেমপ্লেট ব্যবহার করে নিবন্ধটি আকর্ষণীয়" খুঁজে পেতে পারেন। এটি গেম প্রোগ্রামিং রems 5 এর বিভাগ 1.4 তে। দুর্ভাগ্যবশত আমার সাথে আমার কপি নেই, কিন্তু এটির জন্য সন্ধান করুন কারণ আমি মনে করি এটি আপনি কী জিজ্ঞাসা করছেন তা ব্যাখ্যা করে।


আমি সি ++ প্রতিফলন চেয়েছিলেন যখন আমি এই নিবন্ধটি পড়েছি এবং সেখানে যা দেখেছিলাম তার উপর উন্নত। দুঃখিত, কোন আছে। আমি ফলাফলের মালিক নই ... তবে আপনি অবশ্যই আমার যা পেয়েছেন তা পেতে পারেন এবং সেখানে যাবেন।

আমি বর্তমানে গবেষণা করছি, যখন আমি এটি অনুভব করছি, প্রতিফলিত ধরনের সংজ্ঞাগুলি আরও সহজ করতে inherit_linearly ব্যবহার করার পদ্ধতিগুলি অনেক সহজ। আমি আসলে এটি মোটামুটি অনেক দূরে পেয়েছি কিন্তু আমি এখনও যেতে একটি উপায় আছে। C ++ 0x এ পরিবর্তনগুলি এই অঞ্চলে অনেকগুলি সহায়তা হতে পারে।


এই প্রকল্পটি দেখার চেষ্টা করুন http://www.garret.ru/cppreflection/docs/reflect.html সি ++ এ প্রতিফলিত করা হয়েছে। এটি ক্লাসগুলিতে মেটা ডেটা যোগ করে যা আপনি ব্যবহার করতে পারেন।


এই প্রশ্নটি এখন কিছুটা পুরানো (আজকে কেন আমি পুরানো প্রশ্নগুলি আঘাত করি তা জানি না) তবে আমি BOOST_FUSION_ADAPT_STRUCT সম্পর্কে চিন্তা BOOST_FUSION_ADAPT_STRUCT যা কম্পাইল-টাইম প্রতিফলন প্রবর্তন করে।

এটি অবশ্যই আপনার কাছে রান-টাইম প্রতিফলন করার জন্য মানচিত্রের উপরে, এবং এটি খুব সহজ হবে না, তবে এটি এই দিক থেকে সম্ভব, যখন এটি বিপরীত হবে না :)

আমি সত্যিই BOOST_FUSION_ADAPT_STRUCT করার জন্য একটি ম্যাক্রো মনে করি এটি রানটাইম আচরণ পেতে প্রয়োজনীয় পদ্ধতি তৈরি করতে পারে।


এটা সি ++ মত দেখাচ্ছে এখনও এই বৈশিষ্ট্য নেই। এবং C++11 স্থগিত প্রতিফলন খুব ((

কিছু ম্যাক্রো অনুসন্ধান করুন অথবা নিজের তৈরি করুন। Qt প্রতিফলন সঙ্গে সাহায্য করতে পারেন (যদি এটি ব্যবহার করা যেতে পারে)।


এবং আমি একটি টুপি ভালোবাসি, কিন্তু ponies বিনামূল্যে নয়। :-p

http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI যা আপনি পেতে যাচ্ছেন। প্রতিফলন যেমন আপনি চিন্তা করছেন - রানটাইম এ সম্পূর্ণরূপে বর্ণনামূলক মেটাডেটা উপলব্ধ - ডিফল্টরূপে সি ++ এর জন্য বিদ্যমান নেই।


চারপাশে reflection সাঁতার দুটি ধরনের আছে।

  1. একটি ধরনের সদস্যদের উপর পুনরাবৃত্তি দ্বারা পরিদর্শন, তার পদ্ধতি এবং আরও enumerating।

    এই সি ++ সঙ্গে সম্ভব নয়।
  2. কোন শ্রেণী-ধরন (বর্গ, কাঠামো, ইউনিয়ন) একটি পদ্ধতি বা নেস্টেড টাইপ আছে কিনা তা পরীক্ষা করে পরিদর্শন, অন্য কোনও প্রকারের থেকে উদ্ভূত হয়।

    এই ধরনের জিনিস template-tricks ব্যবহার করে C ++ দিয়ে সম্ভব। অনেক জিনিস জন্য boost::type_traits ব্যবহার করুন (একটি টাইপ অবিচ্ছেদ্য কিনা তা পরীক্ষা করে দেখুন)। সদস্য ফাংশনের অস্তিত্ব পরীক্ষা করার জন্য, কোনও ফাংশনের অস্তিত্ব পরীক্ষা করার জন্য একটি টেমপ্লেট লিখতে ব্যবহার করা কি সম্ভব? । একটি নির্দিষ্ট নেস্টেড টাইপ উপস্থিত কিনা তা যাচাই করার জন্য, সাধারণ SFINAE ব্যবহার করুন।

যদি আপনি বরং 1) সম্পন্ন করার উপায়গুলি সন্ধান করছেন, একটি শ্রেণীতে কতগুলি পদ্ধতি রয়েছে তা দেখতে চাইলে বা ক্লাস আইডি এর স্ট্রিং উপস্থাপনাটি পেতে চাইলে, আমি ভয় পাচ্ছি যে এটি করার কোনও স্ট্যান্ডার্ড সি ++ উপায় নেই। আপনি হয় ব্যবহার করতে হবে

  • QT মেটা অবজেক্ট কম্পাইলারের মত একটি মেটা কম্পাইলার যা অতিরিক্ত কোডের তথ্য যোগ করে আপনার কোড অনুবাদ করে।
  • একটি ফ্রেমওয়ার্ক ম্যাক্রো গঠন যা আপনাকে প্রয়োজনীয় মেটা-তথ্য যোগ করার অনুমতি দেয়। আপনাকে কাঠামোর সমস্ত পদ্ধতি, ক্লাসের নাম, বেস ক্লাসগুলি এবং এটির প্রয়োজন অনুসারে সবকিছু বলতে হবে।

সি ++ মনের গতি দিয়ে তৈরি করা হয়। যদি আপনি উচ্চ স্তরের পরিদর্শন চান, যেমন সি # বা জাভা আছে, তাহলে আমি আপনাকে বলতে চাই যে কিছু প্রচেষ্টা ছাড়াই কোন উপায় নেই।


তথ্য বিদ্যমান - তবে আপনার প্রয়োজনীয় বিন্যাসে নয়, এবং কেবলমাত্র আপনি যদি আপনার ক্লাস রপ্তানি করেন। এই উইন্ডোজ কাজ করে, আমি অন্যান্য প্ল্যাটফর্ম সম্পর্কে জানি না। যেমন স্টোরেজ-ক্লাস স্পেসিফায়ার ব্যবহার করে, উদাহরণস্বরূপ:

class __declspec(export) MyClass
{
public:
    void Foo(float x);
}

এটি কম্পাইলারটি ক্লাস ডিফল্ট ডেটা DLL / Exe এ তৈরি করে। কিন্তু এটি এমন একটি বিন্যাসে নয় যা আপনি সহজেই প্রতিফলনের জন্য ব্যবহার করতে পারেন।

আমার কোম্পানিতে আমরা এই মেটাডেটাটিকে ব্যাখ্যা করে এমন একটি লাইব্রেরি তৈরি করেছি এবং ক্লাসে নিজেকে অতিরিক্ত ম্যাক্রো সন্নিবেশ না করেই ক্লাসকে প্রতিফলিত করার অনুমতি দেয়। এটি ফাংশনকে নিম্নরূপ বলা যেতে পারে:

MyClass *instance_ptr=new MyClass;
GetClass("MyClass")->GetFunction("Foo")->Invoke(instance_ptr,1.331);

এটি কার্যকরভাবে করে:

instance_ptr->Foo(1.331);

Invoke (এই_পয়েন্টার, ...) ফাংশন পরিবর্তনশীল আর্গুমেন্ট আছে। স্পষ্টভাবে এভাবে একটি ফাংশন কল করে আপনি কনস্টেটিভ-এর মতো জিনিসগুলিকে সীমাবদ্ধ করছেন এবং তাই, এই দিকগুলি রানটাইম চেক হিসাবে প্রয়োগ করা হয়।

আমি নিশ্চিত সিনট্যাক্স উন্নত করা যেতে পারে, এবং এটি এখন পর্যন্ত Win32 এবং Win64 এ কাজ করে। আমরা ক্লাসে স্বয়ংক্রিয় GUI ইন্টারফেসগুলি, C ++ এর বৈশিষ্ট্যগুলি তৈরি করতে, এক্সএমএল থেকে এবং XML এ স্ট্রিমিং করার জন্য এবং এটির জন্য একটি নির্দিষ্ট বেস ক্লাস থেকে বের হওয়ার দরকার নেই। যদি পর্যাপ্ত চাহিদা থাকে তবে আমরা মুক্তির জন্য আকৃতিতে এটি খারিজ করতে পারি।


প্রতিফলন মূলত কম্পাইলার কোডের পদাঙ্ক হিসাবে ছেড়ে দেওয়ার সিদ্ধান্ত নিয়েছে যা রানটাইম কোড জিজ্ঞাসা করতে পারেন। সি ++ যা আপনি ব্যবহার করেন না সেটির জন্য অর্থ প্রদানের জন্য বিখ্যাত নয়; কারণ অধিকাংশ মানুষ ব্যবহার / প্রতিফলন চান না, সি ++ কম্পাইলার কিছু রেকর্ডিং দ্বারা খরচ এড়ানো।

সুতরাং, সি ++ প্রতিফলন প্রদান করে না এবং এটি সাধারণ নিয়ম হিসাবে নিজেকে "অনুকরণ করা" সহজ নয় কারণ অন্যান্য উত্তরগুলি লক্ষ করেছে।

"অন্যান্য কৌশল" এর অধীনে, যদি আপনার প্রতিফলন সহ কোনো ভাষা না থাকে, তবে এমন একটি সরঞ্জাম পান যা আপনার কম্পাইলাইল সময়তে থাকা তথ্যটি সরাতে পারে।

আমাদের DMS সফ্টওয়্যার পুনঃনির্মাণ সরঞ্জামকিটটি সাধারণ ল্যাঙ্গেজ সংজ্ঞা দ্বারা পরামিতিকৃত সাধারণ কম্পাইলার প্রযুক্তি। এটি সি, সি ++, জাভা, কোবল, পিএইচপি, জন্য ল্যাঙ্গেজ সংজ্ঞা আছে ...

সি, সি ++, জাভা এবং কোবল সংস্করণগুলির জন্য, এটি পার্স গাছগুলি এবং প্রতীক টেবিলের তথ্যগুলিতে সম্পূর্ণ অ্যাক্সেস সরবরাহ করে। যে প্রতীক টেবিলের তথ্যটি আপনি "প্রতিফলন" থেকে চান এমন তথ্যটি অন্তর্ভুক্ত করে। যদি আপনি ক্ষেত্র বা পদ্ধতির কিছু সেটকে গণনা করতে এবং তাদের সাথে কিছু করার জন্য লক্ষ্য করেন তবে ডিএমএসটি আপনি ইচ্ছাকৃত ভাবে প্রতীক টেবিলে যা পাবেন তা অনুযায়ী কোডটি রূপান্তর করতে ব্যবহার করা যেতে পারে।


যদিও প্রতিফলন সি ++ -তে-বাক্সটি সমর্থিত নয়, এটি কার্যকর করা খুব কঠিন নয়। আমি এই মহান নিবন্ধটি সম্মুখীন করেছি: http://replicaisland.blogspot.co.il/2010/11/building-reflective-object-system-in-c.html

নিবন্ধটি আপনি কীভাবে একটি সুন্দর সহজ এবং প্রাথমিক প্রতিফলন ব্যবস্থা বাস্তবায়ন করতে পারেন তা বিস্তারিতভাবে ব্যাখ্যা করে। এটা তার সর্বাধিক কার্যকর সমাধান প্রদান করে নি এবং রুক্ষ প্রান্তগুলি সরানোর জন্য বাকি আছে তবে আমার প্রয়োজনের জন্য এটি যথেষ্ট ছিল।

নিচের লাইন - সঠিকভাবে সম্পন্ন হলে প্রতিফলন পরিশোধ করতে পারে এবং এটি সি ++ এ সম্পূর্ণরূপে কার্যকর।


সি ++ তে প্রতিফলনের জন্য আরেকটি নতুন লাইব্রেরি রয়েছে, এটি RTTR (রান টাইম টাইপ প্রতিফলন, এছাড়াও গিথুব দেখুন)।

ইন্টারফেস C # এ প্রতিফলনের অনুরূপ এবং এটি RTTI ছাড়া কাজ করে।


সম্পাদনা করুন : CAMP আর রক্ষণাবেক্ষণ করা হয় না; দুই ফর্ক পাওয়া যায়:

  • একটিকে CAMP বলা হয় এবং একই API এ ভিত্তি করে।
  • ধারণা একটি আংশিক পুনর্লিখন, এবং এটি পছন্দ করা হবে কারণ এটি বুস্ট প্রয়োজন হয় না; এটি সি ++ 11 ব্যবহার করে।

CAMP একটি এমআইটি লাইসেন্সপ্রাপ্ত লাইব্রেরি (পূর্বে এলজিপিএল) যা সি ++ ভাষা প্রতিফলন যোগ করে। এটি সংকলন একটি নির্দিষ্ট preprocessing পদক্ষেপ প্রয়োজন হয় না, কিন্তু বাঁধাই নিজে তৈরি করা আছে।

বর্তমান টিগেসফ্ট লাইব্রেরী বুস্ট ব্যবহার করে, কিন্তু সি ++ 11 ব্যবহার করে একটি ফর্ক রয়েছে যা বুস্টের প্রয়োজন নেই



যদি আপনি অপেক্ষাকৃত সহজ সি ++ প্রতিচ্ছবি খুঁজছেন হয় - আমি বিভিন্ন উত্স থেকে সংগৃহীত / সংজ্ঞায়িত করেছি এবং তাদের কীভাবে কাজ করে তা তাদের মন্তব্য করেছে। আপনি এখানে থেকে হেডার ফাইল ডাউনলোড করতে পারেন:

https://github.com/tapika/TestCppReflect/blob/master/MacroHelpers.h

সংজ্ঞায়িত সেট, প্লাস কার্যকারিতা উপরে এটি:

https://github.com/tapika/TestCppReflect/blob/master/CppReflect.h https://github.com/tapika/TestCppReflect/blob/master/CppReflect.cpp https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h

নমুনা অ্যাপ্লিকেশনটি জিট রিপোজিটরিতে পাশাপাশি এখানে রয়েছে: https://github.com/tapika/TestCppReflect/

আমি আংশিকভাবে ব্যাখ্যা দিয়ে এখানে অনুলিপি করব:

#include "CppReflect.h"
using namespace std;


class Person
{
public:

    // Repack your code into REFLECTABLE macro, in (<C++ Type>) <Field name>
    // form , like this:

    REFLECTABLE( Person,
        (CString)   name,
        (int)       age,
...
    )
};

void main(void)
{
    Person p;
    p.name = L"Roger";
    p.age = 37;
...

    // And here you can convert your class contents into xml form:

    CStringW xml = ToXML( &p );
    CStringW errors;

    People ppl2;

    // And here you convert from xml back to class:

    FromXml( &ppl2, xml, errors );
    CStringA xml2 = ToXML( &ppl2 );
    printf( xml2 );

}

REFLECTABLEব্যবহার করে ক্লাসের নাম + ক্ষেত্রের নাম ব্যবহার করে offsetof- মেমরি নির্দিষ্ট ক্ষেত্রের কোন স্থানে অবস্থিত তা সনাক্ত করতে। আমি যতদূর সম্ভব সম্ভব .NET পরিভাষা বেছে নেওয়ার চেষ্টা করেছি, কিন্তু C ++ এবং C # ভিন্ন, তাই এটি 1 থেকে 1 নয়। সম্পূর্ণ সি ++ প্রতিফলন মডেলটি TypeInfoএবং FieldInfoশ্রেণীগুলিতে থাকে।

আমি এক্সএমএল ডেমো কোড আনতে এবং এক্সএমএল থেকে এটি পুনরুদ্ধার করতে Pugi এক্সএমএল পার্সার ব্যবহার করেছেন।

তাই ডেমো কোড দ্বারা উত্পাদিত আউটপুট এই মত দেখাচ্ছে:

<?xml version="1.0" encoding="utf-8"?>
<People groupName="Group1">
    <people>
        <Person name="Roger" age="37" />
        <Person name="Alice" age="27" />
        <Person name="Cindy" age="17" />
    </people>
</People>

TypeTraits ক্লাস এবং আংশিক টেমপ্লেট স্পেসিফিকেশনের মাধ্যমে 3-ডি পার্টি ক্লাস / স্ট্রাকচার সাপোর্ট সক্ষম করাও - আপনার নিজস্ব TypeTraitsT ক্লাসকে সংজ্ঞায়িত করতে, একইভাবে সিএসটিআরং বা int- উদাহরণ কোড দেখুন

https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h#L195

এই সমাধান উইন্ডোজ / ভিজ্যুয়াল স্টুডিও জন্য প্রযোজ্য। এটা অন্যান্য অপারেটিং সিস্টেম / কম্পাইলার পোর্ট করা সম্ভব, কিন্তু যে এক না। (যদি আপনি সমাধানটি সত্যিই পছন্দ করেন তবে আমাকে জিজ্ঞাসা করুন, আমি আপনাকে সাহায্য করতে পারব)

এই সমাধান একাধিক subclasses সঙ্গে এক বর্গ এক শট serialization জন্য প্রযোজ্য।

যদি আপনি ক্লাসের অংশগুলিকে ক্রমানুসারে ক্রিয়াশীল করার জন্য প্রক্রিয়াটি অনুসন্ধান করছেন বা কার্যকারিতা প্রতিফলন কল করার জন্য এমনকি নিয়ন্ত্রণ করতে চান তবে আপনি নিচের সমাধানগুলির দিকে নজর দিতে পারেন:

https://github.com/tapika/cppscriptcore/tree/master/SolutionProjectModel

ইউটিউব ভিডিও থেকে আরো বিস্তারিত তথ্য পাওয়া যাবে:

সি ++ রানটাইম টাইপ প্রতিফলন https://youtu.be/TN8tJijkeFE

আমি সি ++ প্রতিফলন কাজ করবে কিভাবে গভীর ব্যাখ্যা করার চেষ্টা করছি।

উদাহরণস্বরূপ নমুনা কোড দেখতে হবে:

https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/testCppApp.cpp

c.General.IntDir = LR"(obj\$(ProjectName)_$(Configuration)_$(Platform)\)";
c.General.OutDir = LR"(bin\$(Configuration)_$(Platform)\)";
c.General.UseDebugLibraries = true;
c.General.LinkIncremental = true;
c.CCpp.Optimization = optimization_Disabled;
c.Linker.System.SubSystem = subsystem_Console;
c.Linker.Debugging.GenerateDebugInformation = debuginfo_true;

কিন্তু এখানে প্রতিটি ধাপ আসলে সি ++ বৈশিষ্ট্য ব্যবহার করে ফাংশন কল ফলাফল __declspec(property(get =, put ... )

যা সি ++ ডেটা প্রকার, সি ++ সম্পত্তি নাম এবং শ্রেণির দৃষ্টান্তের পয়েন্টারের পাথের রূপে সম্পূর্ণ তথ্য পায় এবং সেই তথ্যের উপর ভিত্তি করে আপনি XML, JSON তৈরি করতে পারেন বা এমনকি ইন্টারনেটের মাধ্যমে সিরিয়ালাইজ করতে পারেন।

যেমন ভার্চুয়াল কলব্যাক ফাংশন উদাহরণ এখানে পাওয়া যাবে:

https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/VCConfiguration.cpp

ফাংশন ReflectCopy, এবং ভার্চুয়াল ফাংশন দেখুন ::OnAfterSetProperty

কিন্তু যেহেতু বিষয় সত্যিই উন্নত - আমি প্রথমে ভিডিও মাধ্যমে চেক করার সুপারিশ।

আপনি কিছু উন্নতি ধারনা আছে, আমার সাথে যোগাযোগ বিনা দ্বিধায়।





sfinae