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



সি++ বই (24)

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

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

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

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

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


সি ++ ২0 দিয়ে, আপনি সম্প্রসারণ বিবৃতি পেয়েছেন , যা আপনাকে সংখ্যার ধরনগুলিতে পুনরাবৃত্তি করতে দেয়:

struct my_type {
    double data;
    std::string another_data;
    int last_data;
};

auto object = my_type{};

for...(auto& member : object) {
    using member_type = std::remove_cvref_t<decltype(member)>;
    member = get_data<member_type>();
}

আপনি এখানে অন্য লাইব্রেরি খুঁজে পেতে পারেন: http://www.garret.ru/cppreflection/docs/reflect.html এটি 2 উপায়ে সমর্থন করে: ডিবাগ তথ্য থেকে টাইপ তথ্য পেতে এবং প্রোগ্রামারকে এই তথ্য সরবরাহ করতে দিন।

আমি আমার প্রোজেক্টের জন্য প্রতিচ্ছবিতে আগ্রহী এবং এই লাইব্রেরীটি খুঁজে পেয়েছি, আমি এখনো এটি চেষ্টা করিনি, কিন্তু এই লোকটির অন্য সরঞ্জামগুলি চেষ্টা করেছি এবং তারাও কীভাবে কাজ করে তা আমি পছন্দ করি :-)


আমি স্বয়ংক্রিয় অন্তর্নিহিতকরণ / প্রতিচ্ছবি টুলকিট "আইডিকে" এর অস্তিত্বের বিজ্ঞাপনে বিজ্ঞাপন দিতে চাই। এটি QT এর মতো মেটা-কম্পাইলার ব্যবহার করে এবং মেটা তথ্য সরাসরি বস্তু ফাইলগুলিতে যোগ করে। এটি ব্যবহার করা সহজ বলে দাবি করা হয়। কোন বাহ্যিক নির্ভরতা। এটি আপনাকে std :: স্ট্রিংকে স্বয়ংক্রিয়ভাবে প্রতিফলিত করতে এবং স্ক্রিপ্টগুলিতে এটি ব্যবহার করার অনুমতি দেয়। IDK দেখুন দয়া করে


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


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

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

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

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


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

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

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

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

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

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

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


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

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


প্রতিফলন বাক্সের বাইরে C ++ দ্বারা সমর্থিত নয়। এটি দু: খিত কারণ এটি একটি ব্যথা আত্মরক্ষামূলক পরীক্ষা করে তোলে।

প্রতিফলন করতে বিভিন্ন পন্থা আছে:

  1. ডিবাগ তথ্য ব্যবহার করুন (অ পোর্টেবল)।
  2. ম্যাক্রো / টেমপ্লেট বা অন্য কোনও উত্স পদ্ধতির সাথে আপনার কোড ছিটিয়ে দিন (কুৎসিত দেখায়)
  3. একটি ডাটাবেস উত্পাদন যেমন clang / gcc হিসাবে একটি কম্পাইলার সংশোধন।
  4. Qt moc পদ্ধতি ব্যবহার করুন
  5. প্রতিফলিত বুস্ট
  6. যথাযথ এবং ফ্ল্যাট প্রতিফলন

প্রথম লিঙ্ক সবচেয়ে প্রতিশ্রুতিশীল (মোড এর clang ব্যবহার করে) দেখায়, দ্বিতীয়টি বেশ কয়েকটি কৌশল নিয়ে আলোচনা করে, তৃতীয়টি gcc ব্যবহার করে একটি ভিন্ন পদ্ধতির:

  1. http://www.donw.org/rfl/

  2. https://bitbucket.org/dwilliamson/clreflect

  3. https://root.cern.ch/how/how-use-reflex

সি ++ প্রতিফলনের জন্য এখন একটি কর্মক্ষেত্র গ্রুপ আছে। C ++ 14 @ CERN এর জন্য সংবাদ দেখুন:

13/08/17 সম্পাদনা করুন: আসল পোস্টটি প্রতিফলনের উপর সম্ভাব্য অগ্রগতির একটি সংখ্যা রয়েছে। নিম্নলিখিত বিভিন্ন কৌশল এবং স্থিতি উপর আরো বিস্তারিত এবং একটি আলোচনা উপলব্ধ করা হয়:

  1. একটি সংক্ষিপ্ত মধ্যে স্ট্যাটিক প্রতিফলন
  2. স্ট্যাটিক প্রতিফলন
  3. স্ট্যাটিক প্রতিফলনের জন্য একটি নকশা

তবে এটি C ++ তে প্রতিফলিততার সমর্থনে সম্প্রদায়ের কাছ থেকে অনেক বেশি আগ্রহ না থাকা পর্যন্ত কাছাকাছি + ভবিষ্যতে সি ++ এ একটি মানানসই প্রতিফলন পদ্ধতিতে প্রতিশ্রুতিবদ্ধ দেখাচ্ছে না।

শেষ C ++ স্ট্যান্ডার্ড মিটিংয়ের প্রতিক্রিয়ার উপর ভিত্তি করে বর্তমান অবস্থাটি নীচে দেওয়া হয়েছে:

13/12/2017 সম্পাদনা করুন

প্রতিফলন সি ++ 20 বা আরো সম্ভবত একটি টিএসআর দিকে চলন্ত দেখায়। আন্দোলন তবে ধীর।

15/09/2018 সম্পাদনা করুন

জাতীয় দলনে ব্যালটের জন্য একটি খসড়া টিএস পাঠানো হয়েছে।

টেক্সট এখানে পাওয়া যাবে: https://github.com/cplusplus/reflection-ts


এই প্রশ্নটির উত্তরে, একটি সি ++ প্রতিফলন গ্রন্থাগারের ধারণা। আমি বিকল্পগুলি বিবেচনা করেছিলাম এবং আমার নিজের তৈরি করার সিদ্ধান্ত নিলাম, কারণ আমার সব বাক্সে টিক চিহ্ন দেওয়া একটাকে আমি খুঁজে পাইনি।

যদিও এই প্রশ্নের উত্তরের উত্তর আছে, আমি টন ম্যাক্রো ব্যবহার করতে বা বুস্টের উপর নির্ভর করতে চাই না। বুস্টটি একটি দুর্দান্ত লাইব্রেরি, তবে অনেকগুলি ছোট বিপক সি সি ++ 0x প্রকল্পগুলি যা সহজ এবং দ্রুত কম্পাইলের সময়গুলি রয়েছে। এছাড়াও একটি ++ লাইব্রেরি র্যাপিংয়ের মতো কোনও শ্রেণীকে আলাদা করতে সক্ষম হওয়ার সুবিধা রয়েছে, যা এখনও (+?) সমর্থন করে না C ++ 11। এটি CAMP এর ফর্ক, সি ++ 11 ব্যবহার করে, যা আর বুস্টের প্রয়োজন হয় না


আমি একবার যা করেছি তার মতো কিছু করেছি, এবং উচ্চ স্তরের বৈশিষ্ট্যগুলিতে কিছু স্তর প্রতিফলন এবং অ্যাক্সেস করা সম্ভব হলেও রক্ষণাবেক্ষণের মাথাব্যথাটি এর মূল্য হতে পারে না। আমার সিস্টেমে উদ্দেশ্য-সি এর বার্তা পাসিং এবং ফরোয়ার্ডের ধারণার মতো প্রতিনিধিদের মাধ্যমে UI ক্লাসগুলিকে ব্যবসায়িক লজিক থেকে সম্পূর্ণরূপে আলাদা রাখতে ব্যবহার করা হয়েছিল। এটি করার উপায় হল কিছু বেস বর্গ তৈরি করা যা প্রতীকগুলি ম্যাপিং করতে সক্ষম (আমি একটি স্ট্রিং পুল ব্যবহার করেছি কিন্তু যদি আপনি গতি এবং কম্পাইল-টাইম ত্রুটিটি সম্পূর্ণ নমনীয়তার উপর পরিচালনা করে) এটি ফাংশন পয়েন্টারগুলিতে (আসলে না বিশুদ্ধ ফাংশন পয়েন্টার, কিন্তু Boost সঙ্গে Boost কি অনুরূপ কিছু। ফাংশন - যা আমি সময় অ্যাক্সেস ছিল না)। আপনার সদস্যের ভেরিয়েবলগুলির জন্য একই জিনিস আপনি যতক্ষণ পর্যন্ত কোনও মান বেস প্রতিনিধিত্ব করতে সক্ষম হবেন ততক্ষণ পর্যন্ত আপনি এটি করতে পারেন। সমগ্র সিস্টেম কী-ভ্যালু কোডিং এবং প্রতিনিধিদলের একটি অবিচ্ছিন্ন ripoff ছিল, কিছু পার্শ্বপ্রতিক্রিয়াগুলির সাথে সম্ভবত যেগুলি সম্ভবত তার সমস্ত পদ্ধতি এবং সদস্যদের সাথে মিলিত হওয়ার জন্য সিস্টেম ব্যবহার করে এমন প্রতিটি শ্রেণি পেতে প্রয়োজনীয় সময়ের সমান মূল্যের ছিল : 1) কোন ক্লাস কোনও শ্রেণীতে শিরোনাম অন্তর্ভুক্ত না করে জাল বেস ক্লাসগুলি লেখার জন্য কোনও পদ্ধতিতে কল করতে পারে তাই কম্পাইলারের জন্য ইন্টারফেসটি পূর্বনির্ধারিত করা যেতে পারে; এবং 2) সদস্যের ভেরিয়েবলগুলির প্রাপক এবং সেটারগুলি থ্রেড-নিরাপদ করা সহজ ছিল কারণ তাদের মানগুলি পরিবর্তন করা বা অ্যাক্সেস করা সর্বদা সমস্ত বস্তুর বেস ক্লাসে ২ টি পদ্ধতির মাধ্যমে করা হয়েছিল।

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

সম্ভবত আপনি আরো আকর্ষণীয় যে আপনি একটি ক্লাসের জন্য সংজ্ঞায়িত সমস্ত পদ্ধতি এবং সদস্যদের ডাম্প করতে পারেন, এবং স্ট্রিং ফর্ম কম।

সিস্টেমকে ডাউনসাইডগুলি যা আপনাকে বিরক্তিকর থেকে বিরত রাখতে পারে: সমস্ত বার্তা এবং কী-মান যোগ করা অত্যন্ত ক্লান্তিকর; এটা কোন প্রতিফলন ছাড়া ধীর হয়; আপনি boost::static_pointer_cast দেখতে boost::static_pointer_cast এবং একটি সহিংস আবেগ সহ আপনার কোডবেসে সমস্ত boost::dynamic_pointer_cast ; দৃঢ়-টাইপ সিস্টেমের সীমাবদ্ধতাগুলি এখনও সেখানে রয়েছে, আপনি সত্যিই তাদের কিছুটা লুকিয়ে রেখেছেন তাই এটি সুস্পষ্ট নয়। আপনার স্ট্রিং টাইপস একটি মজার বা অদ্ভুত আবিষ্কার সহজ নয়।

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


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

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


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


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

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

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


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 টি লাইনের জন্য আপনার কোন তৃতীয় পক্ষের লাইব্রেরি দরকার নেই;)


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

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 এ স্ট্রিমিং করার জন্য এবং এটির জন্য একটি নির্দিষ্ট বেস ক্লাস থেকে বের হওয়ার দরকার নেই। যদি পর্যাপ্ত চাহিদা থাকে তবে আমরা মুক্তির জন্য আকৃতিতে এটি খারিজ করতে পারি।


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

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


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

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


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

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

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


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

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

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

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

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


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

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


আপনি যদি কোনও ফাংশনে একটি পয়েন্টার ঘোষণা করেন:

int (*func)(int a, int b);

আপনি এই ফাংশনে মেমরিতে একটি স্থান বরাদ্দ করতে পারেন (প্রয়োজন libdlএবং dlopen)

#include <dlfcn.h>

int main(void)
{
    void *handle;
    char *func_name = "bla_bla_bla";
    handle = dlopen("foo.so", RTLD_LAZY);
    *(void **)(&func) = dlsym(handle, func_name);
    return func(1,2);
}

অভিকেত ব্যবহার করে একটি স্থানীয় প্রতীক লোড করতে, আপনি dlopenকলিং বাইনারি ( argv[0]) ব্যবহার করতে পারেন ।

এই কেবল প্রয়োজন (ব্যতীত অন্য dlopen(), libdlএবং dlfcn.h) আর্গুমেন্ট এবং ফাংশন ধরণ বুদ্ধিমান হয়।


ক্লাসডেস্ক চেক করুন http://classdesc.sf.net । এটি ক্লাস "ডিস্ক্রিপ্টরস" আকারে প্রতিফলন সরবরাহ করে, যেকোনো মানক সি ++ কম্পাইলারের সাথে কাজ করে (হ্যাঁ এটি ভিসুয়াল স্টুডিও এবং GCC এর সাথে কাজ করার জন্য পরিচিত) এবং সোর্স কোড টীকা প্রয়োজন হয় না (যদিও কিছু প্রগমগুলি জটিল পরিস্থিতিতে পরিচালনা করার জন্য বিদ্যমান )। এটি একটি দশকেরও বেশি সময় ধরে উন্নয়নে রয়েছে, এবং এটি বেশ কয়েকটি শিল্প স্কেল প্রকল্পে ব্যবহৃত হয়েছে।


আপনি কি করতে হবে 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 লাইনের নীচে, সি ++ এ প্রতিফলন বাস্তবায়ন করেছি।





sfinae