الدرس 53: القيم مصنفة النوع المعرَّفة من المستخدم User-Defined Literals في Cpp – لغة C++‎

القيم الثنائية مصنفة النوع المُعرّفة من المستخدم (Self-made user-defined literal for binary)

رغم إمكانية كتابة عدد ثنائي في C++‎ 14 على النحو التالي:

int number =0b0001'0101; // ==21

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

template < char FIRST, char...REST > struct binary {
    static_assert(FIRST == '0' || FIRST == '1', "invalid binary digit");
    enum {
        value = ((FIRST - '0') << sizeof...(REST)) + binary < REST... > ::value
    };
};
template < > struct binary < '0' > {
    enum {
        value = 0
    };
};
template < > struct binary < '1' > {
    enum {
        value = 1
    };
};

// عامل قيمة خام مصنفة النوع
template < char...LITERAL > inline
constexpr unsigned int operator "" _b() {
    return binary < LITERAL... > ::value;
}
// عاملُ قيمةٍ خامٍ مصنَّفةِ النوع
template < char...LITERAL > inline
constexpr unsigned int operator "" _B() {
    return binary < LITERAL... > ::value;
}
#include <iostream>

int main() {
    std::cout << 10101_B << ", " << 011011000111_b << 'n'; // تطبع 21, 1735
}

القيم مصنفة النوع المعيارية المُعرّفة من المستخدم (Standard user-defined literals for duration)

الإصدار ≥ C++‎ 14

فيما يلي قيمُ مدةٍ مصنَّفةِ النوع، ومعرَّفة من قِبل المستخدم (duration user literals)، مصرح عنها في فضاء الاسم namespace std::literals::chrono_literals، حيث ‎literals‎ و ‎chrono_literals‎ هما فضاءا اسم ضمنيّان (inline namespaces). يمكن الوصول إلى هذه العوامل باستخدام using namespace std::literals و using namespace std::chrono_literals و using namespace std::literals::chrono_literals.

#include <chrono>
#include <iostream>

int main() {
    using namespace std::literals::chrono_literals;
    std::chrono::nanoseconds t1 = 600ns;
    std::chrono::microseconds t2 = 42us;
    std::chrono::milliseconds t3 = 51ms;
    std::chrono::seconds t4 = 61s;
    std::chrono::minutes t5 = 88min;
    auto t6 = 2 * 0.5h;
    auto total = t1 + t2 + t3 + t4 + t5 + t6;
    std::cout.precision(13);
    std::cout << total.count() << " nanoseconds" << std::endl; 
                          //  8941051042600 nanoseconds
      std::cout << std::chrono::duration_cast  <  std::chrono::hours >  (total).count() << " hours" << std::endl; // ساعتان
}

القيم مصنَّفة النوع المُعرّفة من المستخدم، ذات قيَم long double

يوضّح المثال التالي كيفية استخدام قيم مصنَّفة النوع، مُعرّفة من المستخدم وذات قيَم long double:

#include <iostream>

long double operator "" _km(long double val) {
    return val * 1000.0;
}
long double operator "" _mi(long double val) {
    return val * 1609.344;
}
int main() {
    std::cout << "3 km = " << 3.0_km << " mn";
    std::cout << "3 mi = " << 3.0_mi << " mn";
    return 0;
}

خرج هذا البرنامج هو:

3 km = 3000 m
3 mi = 4828.03 m

السلاسل النصية المجردة القياسية والمعرّفة من المستخدم (Standard user-defined literals for strings)

الإصدار ≥ C++‎ 14

فيما يلي سلاسل نصية مجردةٌ ومُعرّفة من المستخدم (string user literals)، مُصرَّح عنها في namespace std::literals::string_literals، حيث ‎literals‎ و ‎string_literals‎ هما فضاءا اسم مُضمّنان. ويمكن الوصول إلى هذه العوامل باستخدام using namespace std::literals و using namespace std::string_literals و using namespace std::literals::string_literals.

#include <codecvt>
#include <iostream>
#include <locale>
#include <string>

int main() {
    using namespace std::literals::string_literals;
    std::string s = "hello world"s;
    std::u16string s16 = u"hello world"s;
    std::u32string s32 = U"hello world"s;
    std::wstring ws = L"hello world"s;

    std::cout << s << std::endl;
    std::wstring_convert < std::codecvt_utf8_utf16 < char16_t > , char16_t > utf16conv;
    std::cout << utf16conv.to_bytes(s16) << std::endl;
    std::wstring_convert < std::codecvt_utf8_utf16 < char32_t > , char32_t > utf32conv;
    std::cout << utf32conv.to_bytes(s32) << std::endl;
    std::wcout << ws << std::endl;
}

ملاحظة: قد تحتوي السلاسل النصية المجردة على المحرف ‎‎، انظر المثال التالي:

// "foo"s النصية سينتج عنها C منشئات سلاسل
std::string s1 = "foobar"; 

//  '' تحتوي هذه السلسلة النصية في وسطها على محرفين 
std::string s2 = "foobar"s; 

القيم مصنفة النوع المركّبة المعرّفة من المستخدم (Standard user-defined literals for complex)

الإصدار ≥ C++‎ 14

فيما يلي، قيم مركّبة مصنفة النوع ومعرّفة من المستخدم، مُصرًّح عنها فيnamespace std::literals::complex_literals، حيث ‎literals‎ و ‎complex_literals‎ فضاءا اسم ضمنيان. يمكن الوصول إلى هذه العوامل باستخدام using namespace std::literals و using namespace std::complex_literals و using namespace std::literals::complex_literals.

#include <complex>
#include <iostream>

int main() {
    using namespace std::literals::complex_literals;

    std::complex < double > c = 2.0 + 1i; // {2.0, 1.}
    std::complex < float > cf = 2.0f + 1if; // {2.0f, 1.f}
    std::complex < long double > cl = 2.0L + 1il; // {2.0L, 1.L}

    std::cout << "abs" << c << " = " << abs(c) << std::endl; // abs(2,1) = 2.23607
    std::cout << "abs" << cf << " = " << abs(cf) << std::endl; // abs(2,1) = 2.23607
    std::cout << "abs" << cl << " = " << abs(cl) << std::endl; // abs(2,1) = 2.23607
}

هذا الدرس جزء من سلسلة دروس عن C++‎.

ترجمة -بتصرّف- للفصل Chapter 114: User-Defined Literals من كتاب C++ Notes for Professionals


Source link

اظهر المزيد
زر الذهاب إلى الأعلى

أنت تستخدم إضافة Adblock

الاعلانات هي مصدرنا الوحيد لدفع التكلفة التشغيلية لهذا المشروع الريادي يرجى الغاء تفعيل حاجب الأعلانات