Godot: حالة C ++ في Godot

تم إنشاؤها على ١٨ يوليو ٢٠١٧  ·  65تعليقات  ·  مصدر: godotengine/godot

في Godot ما زلنا نستخدم C ++ 98/03. الهدف من هذه المشكلة هو محاولة تحديد ما إذا كان لا يزال يتعين علينا التمسك بها أو يمكننا البدء في استخدام بعض عناصر C ++ الحديثة (C ++ 11/14/17 وحتى 20).

عندما تمت كتابة Godot في البداية ، كان C ++ 03 هو أحدث إصدار وبعد سنوات تم الاحتفاظ بهذا النمط (إصدار المعيار ، وتجنب المكتبة القياسية ، وما إلى ذلك) لتجنب مشاكل التوافق في بعض المجمعين (بعض وحدات التحكم ، حتى الآن) كما اعلم). لكن يجب علينا إعادة فحص هذه المخاوف.

العناصر التي يجب مراعاتها (تهدف هذه القائمة إلى الاستمرار في النمو أو تجاهل بعض الإدخالات ؛ فقط عصف ذهني في البداية):

  • المؤشرات الذكية: هل تتوافق آلية المؤشر / الكائن المخصص من Godot مع ذلك؟ هل سيحتاج Godot إلى إعادة كتابته في جزء كبير لاستخدامها؟ هل ستكون الفوائد أكبر من التكلفة؟
  • نقل دلالات الألفاظ: الأسئلة التي يجب طرحها هنا تشبه إلى حد ما المؤشرات الذكية.
  • auto ، constexpr ، lambdas ، وما إلى ذلك: بشكل عام ، أي ميزة C ++ حديثة تجعل كتابة التعليمات البرمجية أسهل و / أو توفر بعض الفرص للتحسين دون تعطيل النواة الحالية.
  • أساسيات المعالجة المتعددة القياسية : توفر C ++ الآن خيوط المعالجة القياسية ، والذرات ، وحواجز الذاكرة ، وما إلى ذلك. هل يتعين علينا الاحتفاظ بالتطبيقات المخصصة وصيانتها لمنصات مختلفة؟
  • STL / Boost / أخرى : هل سنحصل على بعض الفوائد من خلال التحول من الحاويات المخصصة إلى تطبيق معروف جيدًا؟ Dis / المزايا المتعلقة بالصيانة والأداء والتوافق ، إلخ.
  • register ، تضمين "الحيل" ، وما إلى ذلك : تمت إضافة الأشياء إلى الكود لمحاولة جعل المترجم ينشئ كودًا أكثر كفاءة. بعضها إما تم إهماله أو ليس له تأثير فعلي ، أو حتى يمكن أن يؤدي إلى تفاقم الأداء. الذي يسقط؟ الذي يجب الاحتفاظ به؟
  • إلخ،

يمكن إجراء تغييرات صغيرة في وقت مبكر. ولكن متى يجب أن تحدث التغييرات الكبيرة (في حالتها)؟ جودو 4.0؟ أو بمجرد استقرار Godot 3.0؟

واسمحوا لي أن أدعو بعض الأشخاص بشكل صريح: reduz ، @ punto- ، @ akien-mga ، karroffel ، @ bojidar-bg ،BastiaanOlij ، Faless .

discussion

التعليق الأكثر فائدة

أرغب في عرض 2 (أو 20) سنتًا كشخص جديد على Godot وقاعدة الرموز الخاصة به. أنا أشرف حاليًا وأعمل على جهود نقل معركة ويسنوث إلى جودو. الآن ، الواجهة الأمامية (المحرر و GDScript API) رائعة! إلى جانب بعض الجوانب الصعبة ، فقد سمح لنا حتى الآن بالتقدم بوتيرة جيدة. لكننا تخيلنا أيضًا أننا (الفريق) سنقوم بتقديم تصحيحات للطرف الخلفي (المحرك) في مرحلة ما. تحقيقًا لهذه الغاية ، قمت في وقت سابق من هذا الأسبوع باستنساخ git repo وبدأت في البحث في C ++ ، وبصراحة ... أشعر بالفزع قليلاً.

لدي خبرة في إدارة قاعدة رموز C ++ كبيرة في شكل محرك Wesnoth المخصص القديم. لقد بدأ أيضًا باسم C ++ 03 ، ولكن تم تحديثه لاستخدام ميزات C ++ 11 والإصدارات الأحدث وهو الآن متوافق مع C ++ 14. لقد قادت جهود التحديث هذه (غالبًا بحماس شديد جدًا) وأشعر أنها جعلت قاعدة الرموز الخاصة بنا أكثر قابلية للقراءة وأسهل في العمل معها. من المؤكد أنني لم أعمل مطلقًا على نطاق واسع مع قاعدة رموز C ++ 03 البحتة ؛ لقد تعلمت C ++ باستخدام ميزات C ++ الحديثة. لكن بالنسبة لي ، فإن فكرة أن أشياء مثل auto ، و range-for ، و lambdas تجعل شفرتك أقل قابلية للقراءة هي فقط ... غريبة حقًا.

خذ auto هل من الممكن بالتأكيد إساءة استخدامه والإفراط في استخدامه ، ولكن له أيضًا الكثير من الاستخدامات المشروعة. أحد الأماكن الأكثر شيوعًا التي نشرناها auto عندما قمنا بتحديث قاعدة كود Wesnoth كانت موجودة في حلقات for باستخدام التكرارات. في السابق ، كان لدينا شيء مثل هذا:

for(std::vector<T>::iterator foo = container.begin(); foo != container.end(); ++foo) {}

وهو فوضوي! في الحالات التي احتجنا فيها بالفعل إلى مكرر ، فعلنا ما يلي:

for(auto foo = container.begin(); foo != container.end(); ++foo) {}

نعم ، أنت الآن لا تعرف نوع المكرر الصريح ، لكنك لن تحتاج أبدًا إلى معرفة ذلك. لقد قرأت تعليقًا هنا في بعض المنشورات قائلة إنه يجعل الأمر أكثر صعوبة إذا تم الإعلان عن الحاوية بعيدًا عن بعض الملفات ، ولكن في الحقيقة ، مع محرري الكود الحديث و intellisense لا يمثل ذلك مشكلة كبيرة.

في معظم الحالات ، ننتقل بدلاً من ذلك إلى النطاق لـ:

for(const auto& foo : container) {}

أسرع بكثير في الكتابة وأكثر إيجازًا أيضًا. لا داعي للقلق بشأن إلغاء الإشارة إلى التكرارات داخل الحلقة أو بشأن تتبع المؤشرات. ومن الواضح تمامًا أنك تدور فوق الحاوية بأكملها. مع التكرارات ، يحتاج الأشخاص الذين ليسوا على دراية بالشفرة إلى التحقق مرة أخرى من أن الحلقة تنتقل بالفعل من البداية إلى النهاية.

استخدام auto in range-for loops هنا أيضًا له فائدة إضافية. إنه يجعل شيئًا واحدًا تحتاج إلى تذكره لتحديثه إذا قمت بتغيير نوع الحاوية! لا أستطيع حقًا أن أفهم حجة جوان بأن هذه الأشياء تجعل شفرتك أقل قابلية للقراءة أو أقل سهولة في الفهم. بالنسبة لي ، الأمر عكس ذلك تمامًا.

في فيديو ولاية جودو ذكر أيضًا اللامدا. مرة أخرى ، من الممكن بالتأكيد الإساءة إليهم ، لكنها أيضًا أداة مفيدة بشكل لا يصدق! إليك نموذج شائع رأيته في قاعدة بيانات Wesnoth قبل استخدام C ++ 11:

struct sort_helper {
    operator()(const T& a, const T& B) {
        return a < b;
    }
}

void init() const {
    std::vector<T> foo;
    foo.push_back(T(1));
    foo.push_back(T(2));
    foo.push_back(T(3));

    std::sort(foo.begin(), foo.end(), sort_helper);
}

طويل ، فوضوي ، سخام التعليمات البرمجية. وهذا ما استخدمناه مع C ++ 11:

void init() const {
    std::vector<T> foo {
        T(1),
        T(2),
        T(3),
    };

    std::sort(foo.begin(), foo.end(), [](const T& a, const T& b) { return a < b; });
}

هذه فقط الحالة الأكثر شيوعًا! ونعم ، أعلم أنه يمكنك أيضًا تنفيذ operator< لـ T وأن std::sort يستخدم ذلك افتراضيًا ، لكنه يوضح وجهة نظري. مرة أخرى ، ربما تكون قد تعلمت فقط وعملت بشكل حصري تقريبًا مع C ++ الحديثة ، لكنني أعتقد أن تجاهل أدوات مثل auto و range-for و lambdas عند الاقتضاء هو إطلاق النار على قدمك.

الذي يقودني إلى النقطة التالية. لقد لاحظت أن Godot يستخدم داخليًا العديد من الأنواع المخصصة الخاصة به بدلاً من أنواع STL. إذا كان مصدر قلقك هو قابلية قراءة الكود فيما يتعلق بأشياء مثل auto ، فإن استخدام أنواع أساسية مخصصة على أنواع STL أمر ضار تمامًا! قبل بضعة أيام ، كنت أتصفح قاعدة التعليمات البرمجية ووجدت الكثير من التعليمات البرمجية التي تبدو كالتالي:

container.push_back(T(args));

الآن ، هذا غير فعال. يأخذ push_back (على الأقل من حيث std::vector ) مرجعًا ثابتًا ؛ لذلك ، ينتج عن هذا المشغل نسخة غير ضرورية. كنت أرغب في عمل تصحيح لجعلهم يستخدمون emplace_back ... لكن بعد ذلك أدركت أن قاعدة الكود بأكملها تستخدم أنواع حاوية مخصصة 😐

كانت إحدى المشكلات الكبيرة في تصميم Wesnoth وأحد العوامل الرئيسية المساهمة في اتخاذ قرار باستخدام محرك جديد (في هذه الحالة ، Godot) هي أن Wesnoth عانى من متلازمة Not Invented Here بدرجة كبيرة. بينما استخدمنا مكتبات مثل Boost ، كان خط أنابيب العرض الخاص بنا مخصصًا ، وكانت مجموعة أدوات واجهة المستخدم الخاصة بنا مخصصة ، وكانت لغة البيانات / البرمجة النصية مخصصة ... يمكنك الحصول على الجوهر. قبل أن نبدأ العمل على منفذ Godot ، حاولت (وفشلت) في تنفيذ عرض تسريع الأجهزة (حتى هذه النقطة كنا نستخدم عرض السطح / العفريت المعتمد على وحدة المعالجة المركزية. في عام 2019. نعم ، أعرف X_X). لم يكن لدى واجهة برمجة تطبيقات SDL's Texture دعم shader ، وكان هناك حاجة إلى دعم shader. في النهاية ، قررت أن تنفيذ برنامج العارض الخاص بنا ، على الرغم من أنه ممكن ، من شأنه أن يفرض عبء صيانة غير ضروري على المشروع لاحقًا. لدينا بالفعل عدد قليل من المطورين الأساسيين ، والعثور على شخص قادر على كتابة OpenGL (أو Vulkan إذا احتجنا في أي وقت لإسقاط OGL) سيكون مجرد ألم غير ضروري عندما يكون لمحرك مثل Godot عارض جيد تمامًا وصيانته جيدًا يمكننا استخدامه بدلا من.

لقد طرحت هذا الأمر لأنني أعتقد أنه مثال جيد على أن تنفيذ كل شيء داخليًا يمكن أن يكون فكرة سيئة. نعم ، يمكنك تقليل حجمك الثنائي قليلاً من خلال عدم استخدام المكتبة القياسية ، ولكنك تتحمل أيضًا عبء صيانة ضخمًا. تحويل تلك المكالمات push_back إلى emplace_back هو ثمرة منخفضة جدًا يمكن أن تجعل الكود أنظف وأكثر أداءً. ولكن نظرًا لأن لديك نوعًا مخصصًا من vector ، إذا كنت تريد إنشاءًا في نفس المكان ، فسيتعين على شخص ما تنفيذه يدويًا. وفي جميع الأنواع المخصصة الأخرى أيضًا!

القضية الأكبر هي أنها ترفع الحاجز أمام الدخول. ألقيت نظرة على قاعدة كود جودو متوقعة أنواع C ++ STL. عدم العثور على هذه الوسائل أنا أو أي شخص آخر بحاجة الآن إلى معرفة الأنواع التي يوفرها المحرك بالضبط وما هي واجهة برمجة التطبيقات التي تتوافق مع كل منها. أريد std::map ؟ لا ، أحتاج إلى استخدام dictionary . إنه يجعل الحياة أكثر صعوبة للقائمين على الصيانة ويعقد الأمور للمساهمين الجدد. وفي الحقيقة ، ليست الكود الذي يشبه شيئًا واحدًا ولكنه في الواقع شيء آخر ... غير قابل للقراءة؟

منذ حوالي عام ، عندما أغلقنا إصدار Wesnoth 1.14 وإطلاقه على Steam ، شرعت في مشروع إعادة بناء ديون للتخلص من نوع حاوية مخصص كان أساسًا std::list باستثناء استخدام erase() لم يبطل التكرارات. هنا هو مبدأ الالتزام في السؤال . لقد احتاج الأمر إلى مزيد من العمل بعد ذلك للحصول على المعلومات الصحيحة ، ولكن النتيجة كانت رمزًا أبسط كثيرًا وأسهل في الفهم وأقل غموضًا.

في الختام ، أعتقد أن حظر بعض ميزات C ++ 11 المفيدة جدًا والالتزام بأنواع مخصصة على أنواع STL سيكون عائقًا أمام Godot على المدى الطويل. أعلم أن إعادة هيكلة الأشياء تستغرق وقتًا طويلاً (صدقني ، أعلم) ، ولكن بالطريقة التي تسير بها الأمور الآن يبدو من المحتمل جدًا أن ينتهي بك الأمر مع مصيدة 22. من خلال محاولة تجنب الجوانب السلبية لاستخدام STL (الأحجام الثنائية للجعة ، إلخ) ، سينتهي بك الأمر بجعل الأمر أكثر صعوبة وأكثر صعوبة للتحول إلى كود أفضل أداءً وأنظف في معايير C ++ الأحدث. أنا متأكد من أنه لا أحد يتطلع بشكل خاص إلى تنفيذ البناء في المكان في جميع الأنواع المخصصة. 😬

أعلم أن رأيي لا يعني الكثير هنا ، لكنني اعتقدت أنني سأقدم أفكاري من منظور شخص عمل مع قاعدة رموز C ++ كبيرة انتقلت إلى C ++ الحديثة من C ++ 03. إنه عمل كثير ، لكنني أشعر أنه يستحق ذلك على المدى الطويل.

إسمح لجدار النص الضخم!

ال 65 كومينتر

نوقش هذا عدة مرات ، والإجابات المعتادة هي:

1) لا يوجد رغبة في نقل قاعدة البيانات إلى أي شيء أعلى من 03. الميزات لا تستحق ذلك. بالنسبة إلى GDNative C ++ ، من الممكن تمامًا استخدامه بالرغم من ذلك.
2) لا توجد رغبة في استخدام STL / Boost / Etc. كان الأساس المنطقي دائمًا هو نفسه: أ) تقوم قوالب Godot بأشياء صغيرة لا تفعلها عادةً (على سبيل المثال ، عمليات إعادة العد الذرية والنسخ عند الكتابة) ب) تنشئ STL رموز تصحيح أخطاء ضخمة وثنائيات تصحيح أخطاء بسبب رموزها الطويلة للغاية المشوهة

نحافظ على نفس الطريقة مثل كل شيء.

حصلت على بعض الآراء حول المحادثات الخاصة ، لكنني أردت أن أجعل
مناقشة عامة أكثر.

لم أكن أعلم أنه قد نوقش كثيرًا وأغلق بالفعل.

هل تتجاهل حتى auto و constexpr وما إلى ذلك؟

هل تريد إسقاط "تسجيل"؟

ال 18 يوليو. 2017 الساعة 1:54 مساءً ، "خوان لينيتسكي" [email protected]
escribió:

نوقش هذا عدة مرات ، والإجابات المعتادة هي:

  1. لا يوجد رغبة في نقل قاعدة الشفرة إلى أي شيء أعلى من 03. الميزات هي
    لا يستحق أو لا يستحق ذلك. بالنسبة إلى GDNative C ++ ، من الممكن تمامًا استخدامه بالرغم من ذلك.
  2. لا توجد رغبة في استخدام STL / Boost / Etc. كان الأساس المنطقي دائمًا هو
    نفس الشيء: أ) تقوم قوالب جودو بعمل أشياء صغيرة لا تفعلها عادة (على سبيل المثال ، ذري
    refcounts والنسخ عند الكتابة) ب) ينشئ STL رموز تصحيح أخطاء ضخمة وتصحيح أخطاء
    الثنائيات بسبب رموزها الطويلة للغاية المشوهة

نحافظ على نفس الطريقة مثل كل شيء.

-
أنت تتلقى هذا لأنك قمت بتأليف الموضوع.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/godotengine/godot/issues/9694#issuecomment-316041201 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ALQCtipKmepD_1Xw6iRXZ7aGoQlLfiwFks5sPJzqgaJpZM4ObOio
.

لقد أثرت هذه المشكلة أنه سيكون من الآمن استخدام المؤشرات الذكية وأن هذا الرمز يعاني من متلازمة المعاهد الوطنية للصحة ، لكن المسؤولين الأعلى ليس لديهم نية للترقية ، لذلك أقترح عليك الاستسلام أيضًا.

من المحتمل أن يستغرق الأمر عدة ساعات لترقية الشفرة ، والتي يفضل المطورون إنفاقها على تنفيذ ميزات جديدة. أفهم هذا بطريقة ما - يفضل مستخدمو المحرك الحصول على ميزات جديدة بدلاً من "إعادة البناء" (بدون فهم أشياء مثل الديون التكنولوجية).

Marqin آسف ولكن المؤشرات الذكية فكرة سيئة لأن:

1) المفيد الوحيد هو المعاد عده ، والباقي هو العادة السرية الذهنية لميزات موجودة بالفعل في اللغة.
2) يعد استخدام المؤشرات الذكية في كل مكان فكرة سيئة ، فأنت تخاطر بوجود دورات مرجعية تؤدي إلى تسرب الذاكرة
3) لدينا بالفعل شيء مشابه ، المرجع <> ، مع الميزة الإضافية المتمثلة في أننا نتحكم في كيفية عمل العد المرجعي ، حتى نتمكن من إضافة حالات خاصة للتعامل مع الارتباطات بلغات مثل C # ، مع وجود gc الخاصة بهم

لذا ، قبل المجادلة بأننا نقرر الأشياء لمجرد نزوة ، اسأل فقط. عادة ما نتخذ قرارات مستنيرة ونشارك العملية مع الجميع.

ما يمكن القيام به بسهولة إذا كنت ترغب في تحسين الجودة ، هو البدء في كتابة اختبارات الوحدة (أضف بعض الوظائف الاختيارية إلى scons لذلك ، وقم فقط بتثبيت dev gmock / gtest بأنفسهم [لعدم انسداد ./thirdparty])

الباقي هو استمناء عقلي للميزات الموجودة بالفعل في اللغة

reduz ، كيف تكون لغة Unique_ptr بملكيتها الصريحة وتحرير ذاكرة RAII موجودة بالفعل في اللغة؟

أيضًا ، ليس فقط إدارة الذاكرة ، ولكن أيضًا خيوط المعالجة تصبح أسهل (على سبيل المثال lock_guard ).

RandomShaper أنا لست ضد الترقية في وقت ما في المستقبل ، ولكن على الرغم من وجود العديد من الميزات المفيدة ، فإن إصدارات C ++ الأحدث تميل إلى جعل المبرمج يكتب كودًا أقل وضوحًا. ينتج عن هذا صعوبة في قراءة الكود بشكل عام من قبل الآخرين (نموذجي مع إساءة استخدام الكلمات الرئيسية تلقائيًا).

الميزة الأخرى لعدم استخدام المزيد من الميزات المتقدمة (ig ، نحن لا نستخدم استثناءات ويمكن تعطيل rtti بتكلفة قليلة) هي أن المجمعين ينتجون ثنائيات أصغر بكثير.

هذا جيد. انا احترم كلمتك. أنا فقط أجد أن مناقشة هذا أمر صحي.

أعلم أن بعض شركات ألعاب الفيديو الكبيرة (Ubisoft ، IIRC) قد نقلت قواعد الأكواد الكبيرة إلى C ++ الحديثة ، لذا يجب أن تكون مناسبة تمامًا لـ Godot أيضًا. بالطبع ، كما أشرت ، يتطلب ذلك العمل / الوقت.

لهذا السبب يمكننا:

  • اختيار مجموعة فرعية معقولة لترحيل جميع الرموز غير مؤلم قدر الإمكان ؛
  • أو على الأقل اختيار مجموعة فرعية معقولة على أنها "معتمدة" للرمز الجديد.

في كلتا الحالتين ، من المحتمل أن يحتاج نمط الترميز إلى تعريف حتى لا يسيء استخدام الميزات ، كما قلت إنه يحدث مع auto .

بالطبع ، هناك الآن أشياء ذات أولوية أعلى ، ولكن ربما عندما تصبح 3.0 مستقرة أو في مرحلة أخرى في المستقبل ، سيكون من الجيد أن تكون قد قررت بالفعل.

Marqin كما ذكرنا ، يستخدم Godot مخطط تخصيص الذاكرة الخاص به للعقد ، وهو أمر منطقي أكثر من أي شيء توفره المكتبات القياسية الجديدة.

أيضًا lock guard عبارة عن 3 أسطر تقريبًا من التعليمات البرمجية وقد قمنا بالفعل بتنفيذها دون استخدام C ++ 11 +

مرة أخرى ، لماذا يجب أن نفترض أن أي شيء "قياسي" 1) يحتاج إلى أن يكون أفضل مما لدينا بالفعل 2) أفضل إذا استخدمناه على أي حال؟ اعتقد انها phallacy شائع.

ما التالي ، إسقاط وظائف الطباعة واستخدام ostream / istream؟ قم بتغيير فئة String الخاصة بنا ، وهي رائعة جدًا ، واستبدلها بـ std :: string أو std :: wstring؟

لا تخدم المكتبات القياسية جميع الأغراض ولا تعمل بشكل أفضل من أي شيء آخر لمجرد أنها مكتبات قياسية. إنها موجودة فقط لمن يحتاجون إليها ، ولا بأس من تجاهلها وكتابة تطبيقاتك الخاصة إذا كان لديك سبب وجيه للقيام بذلك. نحن نفعل ذلك ونحن واثقون من ذلك.

RandomShaper المشكلة هي:

1) إنها تكلفة أكثر من الفائدة.
2) سيفتح النافذة أمام الكثير من الحجج حول الطريقة القياسية لكتابة C ++ 11 +. قد يكون من المفيد الحصول عليها في مرحلة ما ، وقد تكون إعادة كتابة جزء كبير من المحرك للاستفادة من هذه الميزات مفيدة ذات يوم ، ولكن أعتقد أن هناك أشياء أكثر أهمية للتركيز عليها.
3) أيضًا كما ذكرنا سابقًا ، قد يكون من الممكن أن يكون الأمر رائعًا مثل نقل الأصوات إلى إصدار C ++ جديد ، وقد ينتج عن ذلك حجم ثنائي أكبر بكثير. في مثل هذه الحالة قد يكون غير مرغوب فيه.

الأمر لا يستحق كل هذا العناء في الوقت الحالي ، يمكننا مناقشته مرة أخرى في غضون سنوات قليلة

ما أعتقد أنه سيكون منطقيًا هو التأكد من قيام Godot بالتجميع باستخدام خيارات مثل --std = c ++ 17 ، بحيث يمكنك بسهولة إحضار مكتبة مكتوبة بلغة C ++ الحديثة إذا كنت بحاجة إلى ذلك. على سبيل المثال ، سأصوت لإزالة الكلمة الأساسية للتسجيل من قاعدة البيانات https://github.com/godotengine/godot/issues/9691

بطريقة أو بأخرى ، أتذكر أنني قرأت في مكان ما أن مجلس التعاون الخليجي 6.3 غير مدعوم (google
يقول أنه كان في https://github.com/godotengine/godot/issues/7703). يزعجني ذلك لأن gcc-6.3 هو المترجم الافتراضي في توزيعة (مستقر دبيان). يمكن لأي شخص أن يؤكد ذلك؟ ولما ذلك؟

efornara بعض مكتبات الطرف الثالث تتطلب بالفعل إصدارات C ++ أحدث ، وهذا جيد لأن Scons تعتني بذلك مع بيئات البناء المستنسخة. تحقق من كود thridparty etc2comp لترى كيف يعمل.

@ karroffel شكرًا ، لم أكن أعرف ذلك.

ستكون مجرد ميزة رائعة بعد ذلك ، ولكنها ليست ضرورية لاستيراد مكتبة (على الرغم من ذلك ، إذا كنت تحتاج إلى تضمين المزيد من godot بالنسبة لكود الغراء ، فقد تتعثر عبر ملف رأس لا يتم تجميعه).

بالمناسبة ، إذا احتاج أي شخص إلى فعل شيء مشابه ووجد هذا المنشور ، فإن الملف ذي الصلة هو: https://github.com/godotengine/godot/blob/master/modules/etc/SCsub . لقد وجدته باستخدام grep ويبدو أنه المكان الوحيد الذي يحتاج إليه في الوقت الحالي.

ليس من الآمن ربط c ++ 11 برمز not-c ++ 11 - http://gcc.gnu.org/wiki/Cxx11AbiCompatibility

Marqin ما لم أسيء فهم الرابط ، يبدو أن هذا في الواقع يدعم حالة godot _not_ البدء في استخدام مكونات من المكتبة القياسية ، ولكن التمسك بالمكونات المخصصة بدلاً من ذلك:

لغة C ++ 98 متوافقة مع ABI مع لغة C ++ 11 ، ولكن هناك عدة أماكن في توافق فاصل المكتبة القياسية.

يبدو خلط اللغات آمنًا إلى حد ما (ليس جيدًا ، أعترف بذلك ، وقد يتوقف عن العمل في المستقبل) ، لكن خلط أشياء مثل الأزواج والمتجهات والقوائم وما إلى ذلك ... من المعروف أنه يسبب مشاكل.

efornara الرابط يتعلق بربط بعض libs الطرف الثالث التي تستخدم C ++ 11 مع Godot التي تستخدم C ++ 03.

Marqin نعم ، لكن الطريقة التي أفهم بها الرابط هي أنه يمكنك فعل ذلك. ما لا يمكنك فعله ، على سبيل المثال ، هو تمرير std :: list <> من godot إلى مكتبة الطرف الثالث.

reduz أين يمكنني العثور على توثيق المرجع الداخلي لغودو <>؟ أين يمكنني العثور على وثائق حول اختلاف حاويات Godot الداخلية عن تلك الموجودة في STL؟

@ مرقين للحاويات لا يوجد الكثير:
http://docs.godotengine.org/en/stable/development/cpp/core_types.html#containers
بالنسبة إلى المرجع <> أدركت أنه لا يوجد أي شيء. ربما ينبغي أن تضاف.
نرحب بشدة بأي اقتراحات حول كيفية تحسين المستند لإضافة هذه الأشياء.

أنا شخصياً أجد معيار C ++ الجديد رائعًا للغاية ، لكنني لن أقترح أي إعادة بناء داخلي في Godot لأنه سيتطلب الكثير من الجهود لتحقيق مكاسب قليلة جدًا.

يعد أيضًا أحد التوافق مع الإصدارات السابقة أحد السمات المميزة لـ C ++ لهذا السبب بالضبط. ولكن ما زلت أرغب في أن أكون قادرًا على استخدامه لميزات Godot الجديدة وفي GDNative.
أفضل أن يتم تجميع Godot مع دعم C ++ الحديث لهذا السبب.

reduz كما قلت ، يتيح لك C ++ 11/14/17 كتابة تعليمات برمجية أقل وضوحًا. حتى لو كان الأمر صعبًا ، يعد هذا عيبًا بالنسبة للمبتدئين في C ++ ، فهو أمر جيد لمستخدمي C ++ المحترفين.
أما بالنسبة إلى "تلقائي" ، فأنا شخصياً أعتقد أنه مفيد لمستخدمي الطاقة أيضًا. لا يسمح لك فقط بتجنب كتابة الأنواع مرارًا وتكرارًا عندما لا يكون ذلك ضروريًا تمامًا ، ولكن يمكنه أيضًا تجنب كتابة بعض الأخطاء.

لمعلوماتك ، قمت بتجميع درجة الماجستير الحديثة (godot3) باستخدام:

scons platform=x11 target=debug tools=yes builtin_openssl=true CCFLAGS=-std=c++17

على امتداد دبيان (مجلس التعاون الخليجي 6.3). بشكل مزعج ، يتم تعيين الخيار أيضًا عند تجميع ملفات C ، لذلك تغمرك التحذيرات إذا قمت بتمكينها ، ولكن بصرف النظر عن ذلك ، سارت الأمور بسلاسة. حتى كلمة التسجيل الرئيسية لا يبدو أنها تسبب مشكلة.

لن أذهب إلى حد اقتراح أن يتم تجميع البنيات الرسمية بهذه الطريقة ، ولكن من الجيد معرفة أن الخيار موجود إذا كنت بحاجة إليه في مشروعك. ما أود أن أقترحه هو أن أي تغييرات تكسر هذا يتم التعامل معها على أنها تراجع.

تحرير: تم تصحيح بعض الأخطاء المطبعية ، مما يجعل بيان التحذيرات أكثر وضوحًا.

مزعج ، يتم تعيين الخيار أيضًا عند تجميع ملفات C.

هل جربت مع CPPFLAGS ؟

Hinsbart لا ، لم أفعل. ربما هناك طريقة ، لكن بما أنني لا أعرف السكونز جيدًا ، فقد ذهبت ببساطة مع ما بدا ممكنًا دون العبث:

$ scons platform=x11 builtin_openssl=true -h | grep FLAGS
CCFLAGS: Custom flags for the C and C++ compilers
CFLAGS: Custom flags for the C compiler
LINKFLAGS: Custom flags for the linker

تحرير: بالمناسبة ، لا أعرف كيف يتم استخدامه في نظام بناء godot ، ولكن CPPFLAGS سيجعلني أفكر في خيارات المعالج المسبق. شخصيًا ، لقد استخدمت دائمًا CXXFLAGS لـ C ++.

هل جربت CPPFLAGS؟

أعتقد أن CPPFLAGS يؤثر على كل لغة تستخدم المعالج المسبق ، لذلك يتم تضمين كل من C و C ++.

@ m4nu3lf يمكنك استخدام أي شكل من أشكال ++ C التي تريدها مع GDNative.

من واقع خبرتي ، فإن أي فرصة لحذف الكود هي فرصة جيدة.

ربما يمكننا إعداد نوع من أنواع صفحات wiki لتوثيق الملفات التي يمكن حذفها واستبدالها بمتغيرات c ++ 11. قد يشمل هذا على الأرجح الأوليات الخيوط وما شابه.

التغيير من أجل التغيير ليس جيدًا (koolaid يضرب به المثل) ، ولكن في هذه الحالة ، انتقل مشروع LLVM والعديد من مشاريع البرمجيات الحرة والمفتوحة المصدر الأخرى لصالح بعض أنماط بناء الجملة الأكثر وضوحًا ، أي التدوين الأحدث للتكرار ، ولكن أيضًا تفريغ فصل الاهتمامات إلى أوقات تشغيل اللغة المعنية ، لأنه (لنكن صادقين) الحفاظ على أقل قدر ممكن من التعليمات البرمجية الخاصة بالمنصة أمر مثالي لمحرك اللعبة.

أفضل رمز تكتبه على الإطلاق هو الرمز الذي ألغيت كتابته. :)

بدافع الفضول ، هل من الممكن كتابة كود يتم تجميعه مع كل من C ++ الأقدم و C ++ الأحدث؟ هل هناك تغييرات كبيرة بين إصدارات C ++؟

بدافع الفضول ، هل من الممكن كتابة كود يتم تجميعه مع كل من C ++ الأقدم و C ++ الأحدث؟ هل هناك تغييرات كبيرة بين إصدارات C ++؟

الأحدث C ++ متوافق مع الإصدارات السابقة مع C ++ الأقدم في 99.99 ...٪ من الحالات (فقط الأشياء التي لم يكن يجب استخدامها أو التي تم تعريفها بشكل سيء تم تعريفها على أنها لم تعد مدعومة ولكن بشكل عام ستؤدي فقط إلى تحذيرات مجمعة ولكنها لا تزال تعمل في الوقت الحاضر) .

ومع ذلك ، فإن C ++ الأحدث لها ميزات مهمة ، ومن الواضح أن تلك الميزات لن تعمل في إصدارات C ++ الأقدم ، وهذه الميزات ليست مجرد ميزات قابلية للاستخدام مثل وحدات الماكرو المتغيرة و auto و lambdas ، ولكن أيضًا ميزات الكفاءة مثل move ing و rvalue المراجع ، وبالطبع وحدات الماكرو المتنوعة ، بالإضافة إلى تلك الخاصة بالسلامة مثل مؤشرات الملكية الأحدث (خاصة مع مكتبات C ++ Core) وغيرها الكثير.

بالنظر إلى أنه حتى Visual Studio يدعم C ++ 17 الحديث الآن ، فلا يوجد سبب لعدم استخدام إصدارات أحدث.

كنت أرغب في التعليق. تمكنت من تجميع godot بعلامة C ++ 17 مع كون المشكلة الوحيدة هي واحدة من عناصر الطرف الثالث التي استخدمت auto_ptr (تمت إزالتها من C ++ 17 نظرًا لمدى سوءها)

لا تكمن المشكلة في عدم تجميعها في c ++ 17 ، فالمشكلة تكمن في الأشخاص الذين يرغبون في استخدام ميزات c ++ 17 ، أو الأسوأ من ذلك ، بدء استخدام العلاقات العامة باستخدام تلك الميزات ... فقط لاكتشاف أن المشروع قيد التشغيل. ++ 03.

يعد نقص لامدا وحدها مشكلة ضخمة لا أراها هنا.
عدة مرات ، يجب على godot تخزين قائمة زمنية من البيانات ، ثم تكرارها.
في كل حالة من هذه الحالات ، يمكن إجراؤها على شكل "for_each" أو بنية مشابهة تتكرر من تلقاء نفسها ، وتبسط كمية هائلة من التعليمات البرمجية ، وتقليل استخدام الذاكرة ، وتحسين الأداء بفضل تضمين lambda / تحسينه. (وهذا هو C ++ 11 ، يُستخدم في كل مكان). نفس الشيء بالضبط لجميع الحلقات العامة في القائمة المرتبطة.

سيسمح مشغلو النقل أيضًا بهياكل بيانات أفضل ، والتي يمكن أن تحل محل الهياكل الرهيبة الحالية بشكل أفضل.

يمكن أن تعطينا أنواع بيانات السلسلة (مثل "mystring" _hs) أو ما شابه ذلك طريقة جيدة لنشر السلاسل المجزأة في كل مكان في الكود ، مما يجعل فحص السلسلة (شائع جدًا في البرنامج النصي ورمز الحدث) أسرع بكثير.

حتى إذا لم يتم استخدام std :: thread (أعتقد أنه تجريد رهيب إلى حد ما) ، فإن مكتبة std atomics مذهلة ومفيدة للغاية. الأمراض المنقولة جنسيا :: الذريوما شابه.

ودعنا لا نتحدث حتى عن مدى إلحاق الضرر بالمشروع نفسه إجبار الأشخاص على استخدام C ++ 03 ، عندما لا يتمكن الأشخاص من دمج المكتبات الحديثة بسهولة ، لأن godot هو مشروع C ++ مفتوح المصدر الوحيد غير المهجور على مثل هذا الإصدار القديم من C ++ ( بقدر ما أعرف)

أنا شخصياً أتفق مع التحفظ وعدم الذهاب إلى أحدث معايير C ++ المطلقة ، لكنني أعتقد أن شيئًا مثل C ++ 11 مع بعض الميزات التي تم فحصها في C ++ 14 هو الأفضل ، وتحسين Godot بشكل كبير. يعد C ++ 11-14 جيدًا بما يكفي لـ Unreal Engine ، الذي ينفذ إلى ps4 و xbox و switch و PC وكمبيوتر شخصي منخفض المستوى و android و IOS و HTML5 webassembly. لا أرى لماذا يجب على godot تقييد نفسه عندما يدعم كمية أقل بكثير من المنصات.

يمكن أن تعطينا أنواع بيانات السلسلة (مثل "mystring" _hs) أو ما شابه ذلك طريقة جيدة لنشر السلاسل المجزأة في كل مكان في الكود ، مما يجعل فحص السلسلة (شائع جدًا في البرنامج النصي ورمز الحدث) أسرع بكثير.

بالإضافة إلى أنه يتيح لك استخدامها في أشياء مثل المفاتيح. مثلما صنعت نوع Atom منذ سنوات لاستبدال تنفيذ سلسلة flyweight:
https://github.com/OvermindDL1/OverECS/blob/master/StringAtom.hpp

يحتوي على 32 بت (5 أحرف كحد أقصى ، أو 6 إذا أعدت ترميز الجدول قليلاً) ، وإصدار 64 بت (10 أو 12 حرفًا كحد أقصى ، اعتمادًا على ما إذا كنت تختار تشفيرًا ضيقًا أم لا). إنه قابل للعكس تمامًا ، يحدث في وقت الترجمة أو ديناميكيًا في وقت التشغيل في أي من الاتجاهين ، ويمكن استخدامه بالكامل في المحولات ، إلخ ... إلخ ... مثال على استخدام هذا الملف:

switch(blah) {
  case "UPDATE"_atom64: ... pass
  case "PHYSUPDATE"_atom64: ... pass
  ...
}

عند التفاعل مع كود LUA ، استخدمت للتو سلاسل وقمت بإجراء التحويل على الحدود. هذا الملف ليس الإصدار "الأحدث" منه ، لقد أضفت وظائف للقيام بالتحويلات بدون تخصيص للذاكرة عند الرجوع من عدد صحيح إلى سلسلة (إنه مخصص أقل على سلسلة -> عدد صحيح بغض النظر ، لأنه يعمل في وقت الترجمة) . من السهل إنشاء مرشح Visual Studio أو GDB لعكس الترميز عند عرض Atom64 / Atom32 / أي نوع أيضًا (وهو مجرد عدد صحيح في الأسفل) حتى تتمكن من رؤية نوع السلسلة بدلاً من بعض القيم المجزأة الغريبة.

لكن أشياء مثل هذه مفيدة للغاية ، خاصة في التعليمات البرمجية الحساسة للأداء ولجعل الكود سهل القراءة ، وهذا يتطلب C ++ 11 فقط ، ولا حتى أي شيء أحدث.

على الأقل أقول إن C ++ 14 يجب أن تكون معيار جودو. قد يكون C ++ 17 رائعًا (بعض التحسينات المفيدة جدًا في الأداء في بعض التعليمات البرمجية الجديدة) ، ولكن C ++ 14 هو بالأحرى حد ​​أدنى عالمي الآن. ولكن بالطبع نظرًا لأن مجلس التعاون الخليجي / clang / VisualStudio وأي شيء آخر يدعم C ++ 17 بشكل جيد الآن (وحتى الأجزاء الكبيرة من C ++ 20) ، فإن C ++ 17 تبدو جيدة أيضًا. ربما ما زلت أختار C ++ 14 لـ "just in-case".

@ OvermindDL1 هذا الشيء Atom رائع ، أحبه. من المؤكد أنه سيتناسب تمامًا مع godot ، حيث يقوم بهذا الشيء بالضبط في كثير من الأحيان.

هذا الشيء Atom رائع ، أحبه. من المؤكد أنه سيتناسب تمامًا مع godot ، حيث يقوم بهذا الشيء بالضبط في كثير من الأحيان.

@ vblanco20-1 حسنًا ، إذا أراد جودو ذلك ، فإنهم أحرار في استيعاب الشفرة. لقد شهدت (وهي سلسلة وزن الذبابة السابقة) استخدامًا طويلاً في محرك C ++ القديم الخاص بي. لقد كان مفيدًا جدًا لعلامات الأحداث الصغيرة ، فقط السلاسل القصيرة لاستخدامها كـ "مفاتيح" للأشياء ، ومن السهل جدًا التنقل ذهابًا وإيابًا عبر Lua / LuaJit ، بالإضافة إلى أن مرشحات مصحح الأخطاء كانت مساعدة هائلة .

يعد نقص لامدا وحدها مشكلة ضخمة لا أراها هنا.

هل أنا الوحيد الذي يعتقد أن لامدا تجعل من الصعب قراءة الكود في معظم الحالات؟

Faless : لا ، أنت لست الوحيد ، أعتقد أن صعوبة قراءة Lambdas هي أحد الأسباب التي جعلت Akien لم يرفع إصدار C ++.

Lambdas هي مجرد وظائف مضمنة صغيرة. أنا لا أعرف ماذا تعلق عليها "يصعب قراءتها". لكنها تسمح بأشياء مثل خوارزمية الفرز حيث ترسل وظيفة المقارنة ، أو بقية مكتبة خوارزميات الأمراض المنقولة جنسياً. كما أنها تسمح لك بحفظ الذاكرة وتحسين الأداء بشكل ملحوظ بفضل إزالة الحاجة إلى المصفوفات الزمنية (والتي تحدث عدة مرات في الكود المصدري مع الثماني والأنظمة الأخرى)

ومع مكتبة الخوارزميات المنقولة جنسياً ، فهذه أسهل طريقة لتعدد مؤشرات البرنامج التي يمكنك الحصول عليها ، فقط من خلال التجميع المتوازي ، والفرز المتوازي ، والتراكم المتوازي.

إنه لأمر مخز أن يقوم الناس بشطبها على أنها "غريبة" ، عندما يمكنهم تحسين جودة الشفرة والأداء وقابلية إعادة الاستخدام كثيرًا.

مثال فعلي لشيء قمت بتطبيقه بالفعل:

//old linked list iteration
while (scenario->instances.first()) {
            instance_set_scenario(scenario->instances.first()->self()->self, RID());
        }
//new (just abstracts above)
scenario->instances.for_each([]( RID& item  ){
    instance_set_scenario(item, RID());
});

هناك أيضًا حالة أخرى ، متكررة مرات عديدة

//old. Note the 1024 array, wich is hard size, and is wasting memory

int culled = 0;
Instance *cull[1024];
culled = scenario->octree.cull_aabb(p_aabb, cull, 1024);
for (int i = 0; i < culled; i++) {

    Instance *instance = cull[i];
    ERR_CONTINUE(!instance);
    if (instance->object_ID == 0)
        continue;

    instances.push_back(instance->object_ID);
}

//NEW. not implemented yet. 0 memory usage, can be inlined, and doesnt have a maximum size. 
//Its also shorter and will be faster in absolutely every case compared to old version.

scenario->octree.for_each_inside_aabb(p_aabb, [](Instance* instance){       
    ERR_CONTINUE(!instance);
    if (instance->object_ID == 0)
        continue;
    instances.push_back(instance->object_ID);
});

مثال فعلي لشيء قمت بتطبيقه بالفعل:

لست متأكدا ما هو المكسب هنا ...

إنه لأمر مخز أن يقوم الناس بشطبها على أنها "غريبة" ، عندما يمكنهم تحسين جودة الشفرة والأداء وقابلية إعادة الاستخدام كثيرًا.

@ vblanco20-1 حسنًا ، سأحاول شرح نفسي.
عادة ما ينتهي الناس بكتابة أشياء مثل:

my_arr.push(
    [par1, par2, par3]{
      somefunc(par1, par2, par3);
    }
);

وبعد ذلك ، في بعض الأماكن الأخرى:

func = my_arr.front();
func();

والذي ، عندما تقرأه ، لا يعطيك أي فكرة عن الوظيفة التي يتم تنفيذها ، ولا ما الذي تبحث عنه. قد يكون الأمر جيدًا إذا كان في نفس الملف ، ولكن ما يحدث إذا قمت بتمرير هذه المجموعة عبر ملفات متعددة هو أن الكود بأكمله يصبح غير قابل للقراءة.

Faless مثالك هو مثال على أسوأ ما يمكنك فعله مع lambdas (وهذا النوع من الاستخدام يجب حظره بالتأكيد).

لا يعد استخدام لامدا "عبر الزمن" استخدامًا جيدًا لها ، حيث سيتعين عليها تخصيصها ، كما أنها تصبح خطرًا كبيرًا ، حيث يمكن أن تتوقف المتغيرات الملتقطة عن كونها صالحة بحلول الوقت الذي تقوم فيه بتنفيذ لامدا (على سبيل المثال ، التقاط المؤشر ثم حذف الكائن قبل استدعاء لامدا ، سيتدلى المؤشر الملتقط). أنا فقط أدافع حقًا عن اللامدا لاستخدامها جنبًا إلى جنب مع هياكل البيانات والخوارزميات ، حيث تستخدمها "على الفور".

في مثال for_each ، فإن for_each غير متوافق مع التغييرات في بنية البيانات الداخلية (على سبيل المثال ، إذا أعدت ترتيب متغيراته قليلاً) ، فإنه يسمح بمزيد من هياكل البيانات "غير الشفافة" (مما يتيح للمطور أن يكون قادرًا على "بسهولة "التغيير من بنية بيانات إلى أخرى لاختبار أيهما قد يعمل بشكل أفضل. من خلال تبني ذلك ، يمكنك تنفيذ هياكل بيانات أكثر تعقيدًا تعمل بشكل غير شفاف ، مع الحفاظ على سهولة استخدام طبقة" الاستخدام ".

إنه يقلل أيضًا من الصيغة المعيارية ويجعل أكثر "وضوحًا" ما يفعله الكود بالفعل (تكرار القائمة المرتبطة). مجرد التخلص من "الذات الأولى () -> الذات () ->" يعد تحسينًا لنفسه.

ضع في اعتبارك أن فوائد هذا تتراكم فعليًا مع المزيد من الاستخدام ، حيث ستكون قادرًا على الحصول على أشياء مثل "unordered_for_each" التي تكرر العقد بالترتيب الموجود في الذاكرة (من خلال المُخصص ، أو إذا كانت القائمة المرتبطة مخزنة في الأعلى مصفوفة) ، أو "reverse_for_each". حتى أشياء مثل "بحث" أو "فرز". (لا أوصي بخوارزميات std :: بهذا القدر ، على الأقل حتى C ++ 20 عندما يتم دمج النطاقات. تطبيق الخوارزميات الخاصة بك كجزء من بنية البيانات الخاصة بك هو أفضل بكثير للاستخدام)

كانت Lambdas في الأساس أول شيء سمحت به Epic Games من C ++ 11 إلى محرك غير واقعي ، جنبًا إلى جنب مع مكتبتها الخاصة من الخوارزميات مثل الفرز ، والتقسيم ، والتصفية ، وإزالة الكل ، والبحث ، وما إلى ذلك. في رمز المحرك ورمز اللعب

رائع ، على الأقل نحن نتفق على أن lamdbas ليست بعض الكأس المقدسة
البرمجة ، وقد حددنا بالفعل قاعدة واحدة حول كيفية عدم استخدامها.

سأقوم بمزيد من البحث حول العروض.

في يوم السبت ، 8 ديسمبر ، 2018 ، 17:06 ، كتب vblanco20-1 < [email protected] :

Faless https://github.com/Faless مثالك هو مثال على
أسوأ ما يمكنك فعله مع لامدا (وهذا النوع من الاستخدام يجب أن يكون بالتأكيد
محظور).

إن استخدام لامدا "عبر الزمن" ليس استخدامًا جيدًا لها ، كما هو الحال بالنسبة لهم
لتخصيصها ، كما أنها تصبح خطرًا كبيرًا ، مثل المتغيرات الملتقطة
ستتوقف عن كونها صالحة بحلول الوقت الذي تقوم فيه بتنفيذ لامدا (على سبيل المثال ،
التقاط مؤشر ثم حذف الكائن قبل استدعاء لامدا ،
سوف يتدلى المؤشر الملتقط). أنا فقط أدافع حقًا عن اللامدا
استخدامها جنبًا إلى جنب مع هياكل البيانات والخوارزميات ، حيث تستخدمها
"فورا".

في مثال for_each ، فإن for_each غير متوافق مع التغييرات في الداخل
هيكل البيانات (على سبيل المثال ، إذا أعدت ترتيب متغيراته قليلاً) ، فإنه يسمح
المزيد من هياكل البيانات "غير الشفافة" (والتي تتيح للمطور أن يكون قادرًا على
تغيير "بسهولة العشوائية" من بنية بيانات إلى أخرى لاختبار أي منها
قد تعمل بشكل أفضل. من خلال تبني ذلك ، يمكنك تنفيذ أكثر من ذلك بكثير
هياكل البيانات المعقدة التي تعمل بشكل غامض ، مع الحفاظ على "الاستخدام"
طبقة سهلة الاستخدام.

إنه يقلل أيضًا من الصيغة المعيارية ويوضح ما هو الرمز
في الواقع (تكرار القائمة المرتبطة). مجرد التخلص من "
first () -> self () -> self "هي تحسين على نفسها.

ضع في اعتبارك أن فوائد هذا تتراكم في الواقع مع المزيد من الاستخدام ، مثل
ستكون قادرًا على الحصول على أشياء مثل "unordered_for_each" التي تتكرر
العقد بالترتيب الذي كانت عليه في الذاكرة (من خلال المخصص ، أو إذا كان
يتم تخزين القائمة المرتبطة في أعلى المصفوفة) ، أو "reverse_for_each". حتى الأشياء
مثل "بحث" أو "فرز". (لا أوصي بخوارزميات الأمراض المنقولة جنسيا بهذا القدر ، في
على الأقل حتى C ++ 20 عند دمج النطاقات. تنفيذ الخوارزميات الخاصة بك
كجزء من بنية البيانات الخاصة بك هو أفضل بكثير للاستخدام)

كانت Lambdas في الأساس أول شيء سمحت به Epic Games من C ++ 11 إلى
محرك غير حقيقي ، جنبًا إلى جنب مع مكتبتهم الخاصة من الخوارزميات مثل الترتيب ،
التقسيم ، والتصفية ، وإزالة الكل ، والبحث ، وما إلى ذلك. منذ ذلك الحين هم في كثير من الأحيان
المستخدمة في الكود المصدري ، سواء في كود المحرك أو كود اللعب

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/godotengine/godot/issues/9694#issuecomment-445474001 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABnBbvBTxThAh0v8AfFCdGsSv2HFnEz6ks5u2_GKgaJpZM4ObOio
.

ميزات C ++ 11 التي من شأنها تحسين إمكانية الصيانة لقاعدة التعليمات البرمجية:

  • override و final
  • نطاق من أجل حلقة
  • nullptr
  • تعداد مكتوب بقوة
  • explicit كلمة رئيسية

ميزات C ++ 11 التي من شأنها تحسين نوعية الحياة:

  • قوس الزاوية اليمنى (ليس أكثر من Vector<Vector> > )

[[nodiscard]] (C ++ 17؟) انظر هنا

لا أعتقد أننا يجب أن نتبنى إصدارًا حديثًا من أجل استخدام أشياء جديدة أو لأن هناك ميزة واحدة أو اثنتين يمكن استخدامها. لن أقترح استخدام شيء يتجاوز C ++ 11 لأن الفائدة لا تستحق ذلك.
مع تطور C ++ ، ينمو stl بشكل أكبر وأكبر ويتم إضافة مئات الخطوط إلى المشروع خلال مرحلة ما قبل المعالج. في معظم الحالات يكون لها تأثير ملحوظ في الأداء.

في معظم الحالات يكون لها تأثير ملحوظ في الأداء.

لا ينبغي على الإطلاق؟ يجب ألا يكون للكود الذي لم يتم تنفيذه أي تأثير على الأداء ما لم يكن لديك خطأ في المترجم أو ما شابه ، وفي الإصدار لا ينبغي أن يكون في الثنائيات النهائية على الإطلاق؟ في كثير من الحالات ، يؤدي مجرد وجود دلالات نقل مناسبة وحدها إلى زيادة الأداء ، في بعض المناطق بشكل ملحوظ ، وعلى الرغم من أن هذا مثال قديم يمكن أن يكون للتوجيهات المحدثة أيضًا تحسينات في الأداء من بين ميزات أخرى.

@ OvermindDL1 نعم ، هكذا يجب أن يكون الأمر من الناحية النظرية.
تحقق من هذا: https://twitter.com/zeuxcg/status/1085781851568914432
لقد رأيت حالات مختلفة مثل هذه في وسائل التواصل الاجتماعي مؤخرًا. إنها ليست مجرد "تجريدات لا تكلفتها" كما ينبغي.

lupoDharkael هذا الموضوع Twitter (بمجرد تحميله أخيرًا ، يعد موقع Holy wow twitter واجهة رهيبة ... ما زلت أنسى ذلك ...) يتحدث فقط عن سرعة compiletime لأن math.h في libstdc ++ أكبر في وضع C ++ 17 (حيث لا يحتوي libc ++ على هذه المشكلة) نظرًا لوجود قدر أكبر من الأحمال الزائدة والميزات لتحسين سرعة وقت التشغيل ، لذا فإن أي تجميع يجلب math.h لديه وقت ترجمة أكبر يبلغ حوالي 300 مللي ثانية في حالة استخدام stdlib الأقدم المحدد بدلاً من stdlib الأحدث. لا يذكر شيئًا عن أداء وقت التشغيل (الذي رأيته فقط أسرع في أوضاع C ++ الأعلى ، اعتمادًا على الميزات المستخدمة ، والسرعة نفسها في أسوأ الحالات). بالنسبة إلى It's not as "zero cost abstractions" as it should. ما زلت غير متأكد مما تشير إليه؟ هل لديك أي روابط لتقارير فعلية عن مشكلات أداء وقت التشغيل ، حيث يبدو أن الموضوع الذي قمت بربطه لا علاقة له بذلك على الإطلاق لأنه كان فقط حوالي 300 مللي ثانية في compiletime عند التحويل البرمجي باستخدام math.h في stdlib الأقدم (أنا لست متأكدًا من أنني أرى مشكلة زيادة 300 مللي ثانية في compiletime لكائن مترجم على أي حال)؟

سأحقق المزيد حول هذا الموضوع.
أتفهم أن التكلفة لها سبب ولكن أوقات التجميع الأكبر هي حقًا ميزة مضادة بالنسبة لي. لدي فقط جهاز كمبيوتر محمول وأعمل على ميزات للمحرك يستغرق وقته لأن الوقت الذي يجب أن أنتظر فيه عملية التحويل البرمجي + الارتباط بعد كل تغيير. زيادة ذلك أكثر بدون فائدة مبررة حقًا ، فقط من أجل استخدام إصدارات أحدث ليست فكرة جيدة.

لدي فقط جهاز كمبيوتر محمول وأعمل على ميزات للمحرك يستغرق وقته لأن الوقت الذي يجب أن أنتظر فيه عملية التحويل البرمجي + الارتباط بعد كل تغيير.

إذا كان لديك ذاكرة تخزين مؤقت مثبتة ، فسيتم قضاء الكثير من الوقت في عملية الإنشاء التزايدية على الارتباط. يمكنك حلق ثانية أو ما شابه باستخدام gold بدلاً من ld للربط ، ومن المحتمل تحسينها أكثر من خلال التبديل إلى lld .

بالتأكيد ، لا أستطيع أن أقول ما يكفي من الخير لكل من ذاكرة التخزين المؤقت والنينجا كمنشئ الدعم (إذا كنت تستخدم cmake أو ما شابه على سبيل المثال) ، كلاهما يوفر الكثير من الوقت!

يمكن أن تكون تصميمات الوحدة الإضافية مدهشة بشكل مدهش ، حيث تقوم بإنشاء ملف جديد unity.cpp أو نحو ذلك يتضمن فقط جميع ملفات cpp في المشروع ، على الرغم من أنه من الناحية الواقعية لديك عادةً ملف وحدة cpp لكل "وحدة" من المشروع بحيث يكون لديك فقط عشرات أو نحو ذلك للحفاظ على الذاكرة منخفضة ، في مقابل تلك الذاكرة الإضافية في وقت التجميع ، يتم تجميعها وروابطها بشكل أسرع. هذه أقل فائدة لإعادة البناء التزايدية وأكثر إفادة لإصدارات الإصدارات.

لإضافة واحد إلى الكومة:
static_assert

على سبيل المثال ، يفترض الاتحاد SpatialMaterial::MaterialKey أن البنية لها نفس حجم uint64_t ، لكن لم يتم التأكيد عليها في أي مكان بقدر ما أستطيع أن أقول.

أراد أن يصفع static_assert(sizeof(MaterialKey) == sizeof(uint64_t)) هناك ، لكن لم يستطع.

والشيء الآخر هو استخدام الفريد pptr لضمان التنظيف المناسب عند التدمير دون الحاجة إلى كتابة الكثير من البيانات المعيارية اليدوية ، ودون استخدام حساب مرجعي غير ضروري.

أرغب في عرض 2 (أو 20) سنتًا كشخص جديد على Godot وقاعدة الرموز الخاصة به. أنا أشرف حاليًا وأعمل على جهود نقل معركة ويسنوث إلى جودو. الآن ، الواجهة الأمامية (المحرر و GDScript API) رائعة! إلى جانب بعض الجوانب الصعبة ، فقد سمح لنا حتى الآن بالتقدم بوتيرة جيدة. لكننا تخيلنا أيضًا أننا (الفريق) سنقوم بتقديم تصحيحات للطرف الخلفي (المحرك) في مرحلة ما. تحقيقًا لهذه الغاية ، قمت في وقت سابق من هذا الأسبوع باستنساخ git repo وبدأت في البحث في C ++ ، وبصراحة ... أشعر بالفزع قليلاً.

لدي خبرة في إدارة قاعدة رموز C ++ كبيرة في شكل محرك Wesnoth المخصص القديم. لقد بدأ أيضًا باسم C ++ 03 ، ولكن تم تحديثه لاستخدام ميزات C ++ 11 والإصدارات الأحدث وهو الآن متوافق مع C ++ 14. لقد قادت جهود التحديث هذه (غالبًا بحماس شديد جدًا) وأشعر أنها جعلت قاعدة الرموز الخاصة بنا أكثر قابلية للقراءة وأسهل في العمل معها. من المؤكد أنني لم أعمل مطلقًا على نطاق واسع مع قاعدة رموز C ++ 03 البحتة ؛ لقد تعلمت C ++ باستخدام ميزات C ++ الحديثة. لكن بالنسبة لي ، فإن فكرة أن أشياء مثل auto ، و range-for ، و lambdas تجعل شفرتك أقل قابلية للقراءة هي فقط ... غريبة حقًا.

خذ auto هل من الممكن بالتأكيد إساءة استخدامه والإفراط في استخدامه ، ولكن له أيضًا الكثير من الاستخدامات المشروعة. أحد الأماكن الأكثر شيوعًا التي نشرناها auto عندما قمنا بتحديث قاعدة كود Wesnoth كانت موجودة في حلقات for باستخدام التكرارات. في السابق ، كان لدينا شيء مثل هذا:

for(std::vector<T>::iterator foo = container.begin(); foo != container.end(); ++foo) {}

وهو فوضوي! في الحالات التي احتجنا فيها بالفعل إلى مكرر ، فعلنا ما يلي:

for(auto foo = container.begin(); foo != container.end(); ++foo) {}

نعم ، أنت الآن لا تعرف نوع المكرر الصريح ، لكنك لن تحتاج أبدًا إلى معرفة ذلك. لقد قرأت تعليقًا هنا في بعض المنشورات قائلة إنه يجعل الأمر أكثر صعوبة إذا تم الإعلان عن الحاوية بعيدًا عن بعض الملفات ، ولكن في الحقيقة ، مع محرري الكود الحديث و intellisense لا يمثل ذلك مشكلة كبيرة.

في معظم الحالات ، ننتقل بدلاً من ذلك إلى النطاق لـ:

for(const auto& foo : container) {}

أسرع بكثير في الكتابة وأكثر إيجازًا أيضًا. لا داعي للقلق بشأن إلغاء الإشارة إلى التكرارات داخل الحلقة أو بشأن تتبع المؤشرات. ومن الواضح تمامًا أنك تدور فوق الحاوية بأكملها. مع التكرارات ، يحتاج الأشخاص الذين ليسوا على دراية بالشفرة إلى التحقق مرة أخرى من أن الحلقة تنتقل بالفعل من البداية إلى النهاية.

استخدام auto in range-for loops هنا أيضًا له فائدة إضافية. إنه يجعل شيئًا واحدًا تحتاج إلى تذكره لتحديثه إذا قمت بتغيير نوع الحاوية! لا أستطيع حقًا أن أفهم حجة جوان بأن هذه الأشياء تجعل شفرتك أقل قابلية للقراءة أو أقل سهولة في الفهم. بالنسبة لي ، الأمر عكس ذلك تمامًا.

في فيديو ولاية جودو ذكر أيضًا اللامدا. مرة أخرى ، من الممكن بالتأكيد الإساءة إليهم ، لكنها أيضًا أداة مفيدة بشكل لا يصدق! إليك نموذج شائع رأيته في قاعدة بيانات Wesnoth قبل استخدام C ++ 11:

struct sort_helper {
    operator()(const T& a, const T& B) {
        return a < b;
    }
}

void init() const {
    std::vector<T> foo;
    foo.push_back(T(1));
    foo.push_back(T(2));
    foo.push_back(T(3));

    std::sort(foo.begin(), foo.end(), sort_helper);
}

طويل ، فوضوي ، سخام التعليمات البرمجية. وهذا ما استخدمناه مع C ++ 11:

void init() const {
    std::vector<T> foo {
        T(1),
        T(2),
        T(3),
    };

    std::sort(foo.begin(), foo.end(), [](const T& a, const T& b) { return a < b; });
}

هذه فقط الحالة الأكثر شيوعًا! ونعم ، أعلم أنه يمكنك أيضًا تنفيذ operator< لـ T وأن std::sort يستخدم ذلك افتراضيًا ، لكنه يوضح وجهة نظري. مرة أخرى ، ربما تكون قد تعلمت فقط وعملت بشكل حصري تقريبًا مع C ++ الحديثة ، لكنني أعتقد أن تجاهل أدوات مثل auto و range-for و lambdas عند الاقتضاء هو إطلاق النار على قدمك.

الذي يقودني إلى النقطة التالية. لقد لاحظت أن Godot يستخدم داخليًا العديد من الأنواع المخصصة الخاصة به بدلاً من أنواع STL. إذا كان مصدر قلقك هو قابلية قراءة الكود فيما يتعلق بأشياء مثل auto ، فإن استخدام أنواع أساسية مخصصة على أنواع STL أمر ضار تمامًا! قبل بضعة أيام ، كنت أتصفح قاعدة التعليمات البرمجية ووجدت الكثير من التعليمات البرمجية التي تبدو كالتالي:

container.push_back(T(args));

الآن ، هذا غير فعال. يأخذ push_back (على الأقل من حيث std::vector ) مرجعًا ثابتًا ؛ لذلك ، ينتج عن هذا المشغل نسخة غير ضرورية. كنت أرغب في عمل تصحيح لجعلهم يستخدمون emplace_back ... لكن بعد ذلك أدركت أن قاعدة الكود بأكملها تستخدم أنواع حاوية مخصصة 😐

كانت إحدى المشكلات الكبيرة في تصميم Wesnoth وأحد العوامل الرئيسية المساهمة في اتخاذ قرار باستخدام محرك جديد (في هذه الحالة ، Godot) هي أن Wesnoth عانى من متلازمة Not Invented Here بدرجة كبيرة. بينما استخدمنا مكتبات مثل Boost ، كان خط أنابيب العرض الخاص بنا مخصصًا ، وكانت مجموعة أدوات واجهة المستخدم الخاصة بنا مخصصة ، وكانت لغة البيانات / البرمجة النصية مخصصة ... يمكنك الحصول على الجوهر. قبل أن نبدأ العمل على منفذ Godot ، حاولت (وفشلت) في تنفيذ عرض تسريع الأجهزة (حتى هذه النقطة كنا نستخدم عرض السطح / العفريت المعتمد على وحدة المعالجة المركزية. في عام 2019. نعم ، أعرف X_X). لم يكن لدى واجهة برمجة تطبيقات SDL's Texture دعم shader ، وكان هناك حاجة إلى دعم shader. في النهاية ، قررت أن تنفيذ برنامج العارض الخاص بنا ، على الرغم من أنه ممكن ، من شأنه أن يفرض عبء صيانة غير ضروري على المشروع لاحقًا. لدينا بالفعل عدد قليل من المطورين الأساسيين ، والعثور على شخص قادر على كتابة OpenGL (أو Vulkan إذا احتجنا في أي وقت لإسقاط OGL) سيكون مجرد ألم غير ضروري عندما يكون لمحرك مثل Godot عارض جيد تمامًا وصيانته جيدًا يمكننا استخدامه بدلا من.

لقد طرحت هذا الأمر لأنني أعتقد أنه مثال جيد على أن تنفيذ كل شيء داخليًا يمكن أن يكون فكرة سيئة. نعم ، يمكنك تقليل حجمك الثنائي قليلاً من خلال عدم استخدام المكتبة القياسية ، ولكنك تتحمل أيضًا عبء صيانة ضخمًا. تحويل تلك المكالمات push_back إلى emplace_back هو ثمرة منخفضة جدًا يمكن أن تجعل الكود أنظف وأكثر أداءً. ولكن نظرًا لأن لديك نوعًا مخصصًا من vector ، إذا كنت تريد إنشاءًا في نفس المكان ، فسيتعين على شخص ما تنفيذه يدويًا. وفي جميع الأنواع المخصصة الأخرى أيضًا!

القضية الأكبر هي أنها ترفع الحاجز أمام الدخول. ألقيت نظرة على قاعدة كود جودو متوقعة أنواع C ++ STL. عدم العثور على هذه الوسائل أنا أو أي شخص آخر بحاجة الآن إلى معرفة الأنواع التي يوفرها المحرك بالضبط وما هي واجهة برمجة التطبيقات التي تتوافق مع كل منها. أريد std::map ؟ لا ، أحتاج إلى استخدام dictionary . إنه يجعل الحياة أكثر صعوبة للقائمين على الصيانة ويعقد الأمور للمساهمين الجدد. وفي الحقيقة ، ليست الكود الذي يشبه شيئًا واحدًا ولكنه في الواقع شيء آخر ... غير قابل للقراءة؟

منذ حوالي عام ، عندما أغلقنا إصدار Wesnoth 1.14 وإطلاقه على Steam ، شرعت في مشروع إعادة بناء ديون للتخلص من نوع حاوية مخصص كان أساسًا std::list باستثناء استخدام erase() لم يبطل التكرارات. هنا هو مبدأ الالتزام في السؤال . لقد احتاج الأمر إلى مزيد من العمل بعد ذلك للحصول على المعلومات الصحيحة ، ولكن النتيجة كانت رمزًا أبسط كثيرًا وأسهل في الفهم وأقل غموضًا.

في الختام ، أعتقد أن حظر بعض ميزات C ++ 11 المفيدة جدًا والالتزام بأنواع مخصصة على أنواع STL سيكون عائقًا أمام Godot على المدى الطويل. أعلم أن إعادة هيكلة الأشياء تستغرق وقتًا طويلاً (صدقني ، أعلم) ، ولكن بالطريقة التي تسير بها الأمور الآن يبدو من المحتمل جدًا أن ينتهي بك الأمر مع مصيدة 22. من خلال محاولة تجنب الجوانب السلبية لاستخدام STL (الأحجام الثنائية للجعة ، إلخ) ، سينتهي بك الأمر بجعل الأمر أكثر صعوبة وأكثر صعوبة للتحول إلى كود أفضل أداءً وأنظف في معايير C ++ الأحدث. أنا متأكد من أنه لا أحد يتطلع بشكل خاص إلى تنفيذ البناء في المكان في جميع الأنواع المخصصة. 😬

أعلم أن رأيي لا يعني الكثير هنا ، لكنني اعتقدت أنني سأقدم أفكاري من منظور شخص عمل مع قاعدة رموز C ++ كبيرة انتقلت إلى C ++ الحديثة من C ++ 03. إنه عمل كثير ، لكنني أشعر أنه يستحق ذلك على المدى الطويل.

إسمح لجدار النص الضخم!

Vultraz أوافق تماما.

بينما ليس لدي أي خبرة (تقريبًا) مع C ++ ، بعد العمل لبعض الوقت مع GDNative + C ++ ، أشارك وجهة نظرك.

قبل أيام قليلة نشرت على reddit في موضوع " هل المساهمة في Godot طريقة جيدة لتعلم ++ C؟ ":

لا أوصي به. من واقع خبرتي في العمل مع GDNative و C ++ ، فقد أعادوا ابتكار العجلة عدة مرات على الأقل (مجموعات ومؤشرات مخصصة). هذه الفئات المخصصة غير موثقة (على الأقل من روابط / رؤوس GDNative C ++ POV - باستثناء دليل واحد يؤدي إلى مشروع تجريبي غير تجميعي آخر مرة حاولت فيها ، لا توجد وثائق في الكود [الرؤوس ، الروابط] ولا في المستندات الرسمية) و لديك سلوك مربك / غير بديهي (على سبيل المثال ، التفاف بعض فئات المحرك في وقت متأخر في المرجع يتسبب في حدوث أعطال عشوائية ، على الرغم من أن المرجع يجب أن يكون شفافًا بشكل بديهي وبالتالي لا ينبغي تغيير سلوك الفصل الذي يتم تغليفه).

أنا أيضًا لست معجبًا بتفضيل نموذج IMO الأقل قابلية للقراءة بدلاً من استخدام ميزات C ++ الجديدة. أنا أحب هاسكل (ومكتباتها) ، إيجازها ، وليس قوادة للمبتدئين حتى لا تشل اللغة للمستخدمين المتقدمين.

بسبب هذه القرارات / القيم أشك في أنني سأساهم في المحرك. (إنه أمر مضحك ، لأن مطوري المحرك يذكرون أن السبب وراء هذه القرارات هو تشجيع المساهمات. في حالتي كان له تأثير معاكس تمامًا).

Vultraz كتابة مفصلية جيدًا ، قراءة رائعة ، شكرًا على ذلك. من الجيد سماع منظور كهذا.

أنا مبرمج على النمط القديم C ++ ، وعلى هذا النحو لم أواجه الكثير من المشاكل في فهم كود مصدر Godot ، فقد وجدته منظمًا جيدًا ويروق لي كثيرًا. أعتقد أن التمكن من إضافة دعم VR إلى جوهر هذا المحرك بسرعة نسبية مع امتلاك خبرة قليلة جدًا مع قاعدة الكود هو شهادة على مدى سهولة قراءة هذا المحرك وفهمه. قد تكون المدرسة قديمة من بعض النواحي ، لكنني أتفاجأ باستمرار بمدى جودة بناء أجزاء معينة. نعم ، هناك أجزاء تحتاج إلى تحديث لكي تكون أقل جوعًا للذاكرة وأكثر أداءً ، ولكن بشكل عام ، لقد أعجبت بها.

عندما أسمع الناس يتحدثون عن بناء الجملة الأحدث في C ++ ، غالبًا ما أشعر فقط بالشيخوخة وأتساءل حقًا عن سبب هذه الضجة. لكنني أفهم ذلك نوعًا ما عندما تتعلم المزيد من لغة C ++ الحديثة ثم قررت المساهمة في Godot ، فمن الغريب أن يبدو الأمر وكأنك تعيد اختراع العجلة. لكن بالنسبة لأشخاص مثلي على الأقل ، فقد اعتدنا على رؤية مثل هذه الفصول الدراسية مطبقة ، لقد أعجبنا فقط بمدى جودة تنفيذ معظمها هنا :)

الآن بعد كل ما قيل ، هناك العديد من الطرق المختلفة للنظر في هذه المشكلة ، ليس من المضحك. من أصول Godot التي سبقت بناء جملة C ++ الأحدث إلى ما يشعر به المطورون الأساسيون أكثر في المنزل مع القيود التي تفرضها طبيعة النظام الأساسي المتقاطع لـ Godot والأجهزة (بعضها غير عام) التي يمكن (/ يمكن) تشغيلها. لا أشعر أن هناك صوابًا أو خطأً في هذا ، إنه ما اعتدت عليه ومن أين أتيت ، والسؤال حول ما إذا كان منحنى التعلم الإضافي الذي يتعلم كيف يعمل Godot يفوق فوائد إعادة بناء كود كبير قاعدة.

لا أعرف ما إذا كنت قد شاهدته ولكن خوان أجرى حديثًا في GDC تم وضعه على الإنترنت: https://www.youtube.com/watch ؟
خلال الأسئلة والأجوبة في النهاية تحدث قليلاً عن اتخاذ القرار حول هذا الموضوع.
إنها مشاهدة جيدة.

بالنسبة لردود الفعل المذكورة أعلاه على GDNative ، الأشخاص العاديون ، فإن GDNative هي إضافة حديثة تلبي حاجة معينة ، ولا تدل على كيفية هيكلة المنتج الأساسي وبنائه.
حاول بناء وحدة نمطية (https://docs.godotengine.org/en/3.1/development/cpp/custom_modules_in_cpp.html) ، نعم يتطلب تجميع التغييرات في المنتج الأساسي وهي المشكلة التي يحاول GDNative حلها ، ولكن هذا يعطي لك فهم أفضل لكيفية هيكلة المحرك حقًا. العديد من الحجج التي تم التخلي عنها أعلاه هي أوجه قصور في GDNative ، وليس في Godot نفسها.
أرغب في حل وحدة ديناميكية يسمح لي ببناء الوحدات بنفس الطريقة التي نبني بها الوحدات الثابتة ، ربما يومًا ما سيكون ذلك ممكنًا ، ولكن حتى ذلك الحين يكفي GDNative.

Vultrazmnn يمكنني بالفعل رؤية النقطة المتعلقة بحاويات STL ، ولكن فقط لأن بعض التطبيقات (MSVC ، في الغالب) لها أداء بطيء بشكل رهيب في وضع التصحيح. ولكن يمكن للمرء ببساطة استخدام ملف STL الخاص بـ EA ويكون جيدًا (نظامهم سريع ومحمول).

أيضا: أنا شخصيا وجدت أن عدم وجود RAII هو أكثر ما يزعجني. إن مقدار التنظيف اليدوي الذي يتم إجراؤه بدون داعٍ في جميع أنحاء الكود غريب ، نظرًا لأن RAII ليس جديدًا على C ++ 11.

بالنسبة لردود الفعل المذكورة أعلاه على GDNative ، الأشخاص العاديون ، فإن GDNative هي إضافة حديثة تلبي حاجة معينة ، ولا تدل على كيفية هيكلة المنتج الأساسي وبنائه.

هذا صحيح بالطبع ، ولكن لا ينبغي أن يكون GDNative أكثر سهولة في الاستخدام من المحرك نفسه ، حيث يتم استخدام GDNative لإنشاء "نصوص" ، بحيث يستهدف الجمهور الذي يُتوقع أن يتمتع بمهارات أقل في C ++ لدرجة أن أولئك الذين يرغبون في الانغماس في الأجزاء الداخلية من المحرك؟

بسبب هذه القرارات / القيم أشك في أنني سأساهم في المحرك. (إنه أمر مضحك ، لأن مطوري المحرك يذكرون أن السبب وراء هذه القرارات هو تشجيع المساهمات. في حالتي كان له تأثير معاكس تمامًا).

أنا مستجد C ++ (حوالي شهرين أعمل يومين في الأسبوع في C ++) ، لذلك كان يجب أن أكون الهدف الديموغرافي المستفيد من هذا القرار. أجد أن حاويات Godot تفتقر إلى الوظائف الأساسية (مقارنة بـ stl التي ليست غنية جدًا بحد ذاتها) ، لا أعتقد أن الحاويات مرتبطة بـ GDNative ، لكن قد أكون مخطئًا. أبذل قصارى جهدي لتفادي حاويات Godot ، لأنها دائمًا ما تتألم للعمل معها. اعتقدت أن السلوك غير المتسق وغير المتوقع للمراجع هو مسؤولية المحرك ، لكني أعتقد أنني مخطئ.

أدرك أن خلفية البرمجة الخاصة بي ربما تكون غير عادية إلى حد ما - سنوات العمل الاحترافية في JS / TS ، وسنة في Scala ، ومشاريع الهوايات الأصغر في Haskell (بضعة آلاف من السطور ، وهي في الواقع ليست بهذه الصغر بالنظر إلى مدى إيجاز Haskell - مرات عديدة أكتب الكود بلغة C ++ التي ستكون أقصر في هاسكل بخمس مرات على الأقل وأكثر قابلية للقراءة). أتساءل عما إذا كنت أنا الوحيد الذي يشعر بالإحباط بسبب استخدام التكنولوجيا القديمة المفرطة في الإسهاب.

mnn ، تم إنشاء GDNative لتمكين إنشاء وحدات قائمة على لغة C كمكتبات ديناميكية حتى لا تضطر إلى إعادة ترجمة المحرك بالكامل. علاوة على ذلك ، تم إنشاء العديد من روابط اللغة بحيث يمكنك كتابة وحدات في C ++ ، و python ، و rust ، وما إلى ذلك ، والتي لم تتطلب تجميع المحرك بالكامل.

كان الهدف الآخر من ذلك هو أن يتمكن المطورون من إنشاء وحدات حيث تقوم فقط بتسليم الوحدة نفسها واستخدامها فقط مع بنية مستقرة للمحرك. أصبحت العديد من الوحدات النمطية غير صالحة لأنها لم يتم صيانتها بعد مرتبطة بإصدار معين من المحرك.

حسنًا ، لقد جعل إنشاء الوحدات النمطية من منظور التجميع والنشر أسهل وأبسط بكثير. ولكن بسبب نهجها لها حدودها. عندما تظل ضمن هذه القيود ، يمكن أن تظل كتابة كود C ++ في GDNative أمرًا بسيطًا ، لأنه بقدر ما يكون موضوع ما تقوم ببناء وحدة نمطية له أمرًا بسيطًا.

حاول كسر هذه القيود وستكون مصابًا بالصداع. يدور صداقي الحالي حول محاولة تنفيذ منطق OpenGL بينما يتم تغليف كل ذلك داخل بنية الخادم المرئية ولا يتوفر حقًا داخل GDNative بالطريقة التي أحتاجها. ولكن هذا هو أكثر من عامل رغبتي في القيام بشيء ما باستخدام GDNative لم يتم تصميمه من أجله مطلقًا.
عند استخدامه لما تم تصميمه من أجله ، يمكنك القيام ببعض الأشياء الرائعة حقًا به.

لاحظ أيضًا أن GDNative كان يُقصد به أن يكون وسيلة لإعادة كتابة كود GDScript الذي يجب أن يكون أكثر أداءً. نتيجة لذلك ، لا يمكنك الوصول إلى أي شيء داخل المحرك لا يستطيع GDScript الوصول إليه (مثل OpenGL)

ماذا عن أحدث دعم coroutine ، ie co_await ()؟ من منظور procgen ، هذا ضخم.

يعد دعم Coroutine جزءًا من معيار C ++ 20 ، والذي لم يتم الانتهاء منه بعد ، للتسجيل.

اسمح لي بالتناغم ، فأنا حاليًا أكتب أدوات فرشاة / csg متقدمة (أعتقد محرر مطرقة المصدر) للمحرر المكاني ثلاثي الأبعاد وهذا الحديث عن عدم السماح تلقائيًا أمر محير حقًا بالنسبة لي. في بعض الأحيان ، يمكن أن يكون استخدام السيارة صريحًا. ضع في اعتبارك ما يلي:

أنا داخل SpatialEditorViewportContainer وأريد الحصول على SpatialEditor ، وهو عبارة عن ثلاثة عناصر في التسلسل الهرمي الرئيسي (قبل أن يشير أي شخص إلى أن هناك طرقًا أفضل للوصول إلى SpatialEditor من حاوية منفذ العرض ، يرجى مراعاة أنني بدأت في البحث في قاعدة التعليمات البرمجية هذه في الامس)

auto sp = Object::cast_to<SpatialEditor>(get_parent()->get_parent()->get_parent());

كما ترى ، فإن التقليل الديناميكي _يوضح بالفعل نوع SP_ بشكل صريح. بدون السيارات ، سأضطر إلى كتابة رسائل غير مهمة زائدة عن الحاجة مثل:

SpatialEditor sp = Object::cast_to<SpatialEditor>(get_parent()->get_parent()->get_parent());

من فضلك ، من أجل حب الله ، تسمح باستخدام السيارات!

حول موضوع معيار C ++ لاستخدامه: ستكون ميزات الانعكاس والفئة الوصفية المقترحة لـ C ++ 20 وما بعدها مفيدة حقًا لتقليل الفوضى الكلية مثل

GDCLASS(SpatialEditorViewportContainer, Container);

أيضًا ، أود أن أكرر أن هذه القيود تجعلني أخمن حقًا في قراري بالمساهمة على الإطلاق. في عام 2012 ، علمت نفسي بنفسي C ++ 11 وعدم القدرة على استخدام هذا المعيار يبدو وكأنه صفعة على الوجه. C ++ 11 و C ++ 03 لغات مختلفة تمامًا ، ومعظم السمعة التي يصعب تعلمها في C ++ ، وصعوبة قراءتها وصعوبة كتابتها هي خطأ C ++ 03 (أو 98 بالأحرى). عدم استخدام C ++ 11 أو 14 على الأقل يعتبر _detrimental_ للحفاظ على سهولة القراءة. لقد نشأت مع C ++ 11 ومن الواضح أن قائد المشروع لم يفعل ذلك (عندما بدأ العمل على godot في عام 2007 ، كان عمري 12 عامًا) ، لذلك أعتقد أن هذه حالة تفضيل ومتلازمة بطة الطفل. أشعر أن عدم استخدام C ++ 11 هو فقط لتهدئة الأشخاص الذين اعتادوا على المدرسة القديمة (ويعرف أيضًا باسم الرهيب) C ++ ، على حساب أشخاص مثلي الذين استغرقوا وقتًا لتعلم C ++ الحديثة.

مع مرور الوقت ، سيتم تربي المزيد والمزيد من المبرمجين المبتدئين مثلي على C ++ 11 الحديثة وما بعدها وسيجدون حقيقة أن المشروع عالق إلى الأبد في لغة لا تحتوي حتى على lambdas لتكون محبطة إلى حد ما.

باختصار: C ++ 11 أو التمثال!

لأكون واضحًا ، أنا لا أدعو إلى استخدام المحكمة الخاصة بلبنان. إن لف حاوياتك الخاصة أمر جيد ، لكن رفض ميزات مثل lambdas و auto يبدو غير عادي.

سأغلق غرفة الصدى الآن لأنه من غير المجدي إجراء مزيد من المناقشة هنا. لقد ناقشنا بالفعل منذ أشهر نوع ميزات C ++ 11 و / أو بعض الإصدارات الأحدث التي نخطط لاستخدامها.

نحن فقط في انتظار hpvb لإتاحة الوقت لوضع اللمسات الأخيرة على الإرشادات التي يكتبها بناءً على إجماعنا ، ويمكننا بعد ذلك مناقشة المزيد حول هذه الإرشادات بمجرد نشرها. حتى ذلك الحين ، هذا ليس بناء.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات