استخدام std::apply على std::expected في C++23

C++

تبسيط معالجة الأخطاء في C++23

يعد التعامل مع الأخطاء وإدارة قيم الإرجاع بشكل فعال أمرًا ضروريًا في تطوير C++ اليوم. تتضمن الطريقة النموذجية للعمل مع الوظائف التي تُرجع الأنواع {std::expected} الكثير من عمليات التحقق ورموز معالجة الأخطاء، مما قد يؤدي إلى تعقيد المنطق ويجعل صيانة التعليمات البرمجية أكثر صعوبة.

تبحث هذه الورقة في استخدام طريقة أكثر تعقيدًا وعامة لتبسيط إدارة الأخطاء. من أجل تقليل التعليمات البرمجية المعيارية وتحسين إمكانية القراءة، سندرس إنشاء طريقة `magic_apply` التي تجمع نتائج العديد من قيم {std::expected} وتمريرها إلى وظيفة أخرى.

يأمر وصف
std::expected نوع القالب المستخدم في لغة C++ لمعالجة الأخطاء وله القدرة على تخزين كل من القيم والأخطاء.
std::unexpected عند استخدامه مع std::expected، فإنه يمثل قيمة خطأ غير متوقعة.
template<typename...> يحدد قالبًا متنوعًا بكمية لا حصر لها من وسائط القالب التي يمكنه قبولها.
decltype يستخدم في برمجة القوالب وخاصة لمعرفة نوع التعبير.
args.value() إذا كان للكائن std::expected قيمة، فإنه يصل إلى القيمة الموجودة فيه.
args.has_value() التحقق من وجود قيمة في كائن std::expected.
(... && args.has_value()) لتحديد ما إذا كان كل كائن std::expected له قيم أم لا، قم بطي التعبير.
func(args.value()...) يستخدم قيم الكائنات std::expected لاستدعاء الطريقة func.
return unexpected<Err>(args.error()...) إرجاع خطأ غير متوقع يحتوي على الأخطاء من الكائنات std::expected.

الإدارة الفعالة للأخطاء باستخدام القوالب المتغيرة

ال يتم استخدام النوع في البرامج النصية لتسهيل معالجة الأخطاء في C++ 23. الهدف الرئيسي هو تطوير وظيفة عامة تسمى التي يمكن أن تنقل إخراج عدة القيم إلى وظيفة أخرى. من خلال القيام بذلك، يتم التحقق من الأخطاء المملة التي عادة ما تكون ضرورية عند العمل مع الكثيرين std::expected يتم تقليل القيم. مرن للغاية لأنه قد يستغرق أي عدد من المعلمات باستخدام قوالب Variadic. قبل استدعاء الوظيفة بمحتويات أي كائن، المنطق الأساسي ل magic_apply يستخدم تعبير أضعاف، ، للتأكد من كل شيء الكائنات لها قيم صالحة.

تم توضيح هذه الفكرة في المثال النصي الأول باستخدام أنواع بسيطة مثل و . ويحدد أ الوظيفة التي تنفذ العمليات الحسابية الأساسية، و getA و الوظائف التي تعود أنواع. إذا كانت كلتا القيمتين من و getB شرعية، يمكننا أن ندعو استخدام ; إذا لم يكن الأمر كذلك، فسيتم نشر الخطأ. من خلال تقليل التعليمات البرمجية المعيارية، تعمل هذه الطريقة على تحسين إمكانية القراءة وقابلية الصيانة. يتم تقديم فكرة مماثلة في النص الثاني، ولكن لتسليط الضوء على تنوع النهج، أنواع و lambda functions تستخدم.

تقليل التعقيد في معالجة أخطاء C++ باستخدام `std::expected}

البرنامج النصي C++23 باستخدام قوالب Variadic

#include <expected>
#include <string>
#include <iostream>
#include <tuple>

using namespace std;

template<typename Func, typename... Args, typename Err>
auto magic_apply(Func func, const expected<Args, Err>&... args) -> expected<decltype(func(args.value()...)), Err> {
    if ((... && args.has_value())) {
        return func(args.value()...);
    } else {
        return unexpected<Err>(args.error()...);
    }
}

expected<int, string> getA(int x) {
    if (x > 0) return x;
    return unexpected<string>("Error in getA");
}

expected<double, string> getB(double y) {
    if (y > 0) return y;
    return unexpected<string>("Error in getB");
}

double compute_all(int a, double b) {
    return a + b;
}

int main() {
    auto result = magic_apply(compute_all, getA(10), getB(20.5));
    if (result) {
        cout << "Result: " << result.value() << endl;
    } else {
        cout << "Error: " << result.error() << endl;
    }
    return 0;
}

الجمع بين قيم {std::expected} المختلفة لقيم C++23

البرنامج النصي C++23 باستخدام وظائف Lambda

#include <expected>
#include <string>
#include <iostream>

using namespace std;

template<typename Func, typename... Args, typename Err>
auto magic_apply(Func func, const expected<Args, Err>&... args) -> expected<decltype(func(args.value()...)), Err> {
    bool all_valid = (args.has_value() && ...);
    if (all_valid) {
        return func(args.value()...);
    } else {
        return unexpected<Err>(args.error()...);
    }
}

expected<string, string> getA(bool flag) {
    if (flag) return "SuccessA";
    return unexpected<string>("Failed A");
}

expected<string, string> getB(bool flag) {
    if (flag) return "SuccessB";
    return unexpected<string>("Failed B");
}

string compute_all(const string& a, const string& b) {
    return a + " and " + b;
}

int main() {
    auto result = magic_apply(compute_all, getA(true), getB(true));
    if (result) {
        cout << "Result: " << result.value() << endl;
    } else {
        cout << "Error: " << result.error() << endl;
    }
    return 0;
}

تحسين معالجة أخطاء C++ باستخدام القوالب المتغيرة

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

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

الأسئلة المتداولة حول قوالب Variadic وstd::expected

  1. ما هو ؟
  2. إنه نوع قالب C++ يمكنه الاحتفاظ بخطأ أو قيمة صالحة ويستخدم لإدارة الأخطاء.
  3. كيف عمل؟
  4. إنه يلغي الحاجة إلى عمليات التحقق من الأخطاء المتكررة من خلال الجمع بين نتائج عديدة القيم وتمريرها إلى وظيفة.
  5. ما هي القوالب المتنوعة؟
  6. توفر القوالب المتغيرة قدرًا كبيرًا من الحرية في تصميم الوظائف من خلال تمكين الوظائف من قبول عدد عشوائي من المعلمات.
  7. لماذا تستخدم في ؟
  8. الاستفادة من قيم كائنات لتحديد نوع الإرجاع للوظيفة التي يتم استدعاؤها تلقائيًا.
  9. يكون قادر على التعامل مع أنواع الأخطاء المختلفة؟
  10. نعم، يمكن جعله يعمل مع القيم التي تحتوي على أنواع أخطاء مختلفة مع بعض التعديلات.
  11. ما هي المزايا التي يستخدمها يعرض؟
  12. عند التعامل مع الأخطاء، فإنه يوفر أسلوبًا أكثر تعبيرًا ونظافة من الأساليب التقليدية مثل الاستثناءات أو رموز الإرجاع.
  13. يكون جزء من ؟
  14. بالإضافة إلى , في الواقع، يمثل قيمة غير صحيحة.
  15. هل يمكن استخدام الإجراءات غير المتزامنة مع ؟
  16. إنها بالفعل قابلة للتكيف في التعامل معها القيم التي يتم إرجاعها بواسطة العمليات غير المتزامنة.
  17. ما هو التعبير أضعاف؟
  18. هنا، يتم استخدام الميزة الموجودة في C++ والتي تسمى تعبير الطي للتحقق مما إذا كان كل شيء تحتوي الكائنات على قيم صالحة بطريقة بسيطة.

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