ICECREAM-CPP هي مكتبة صغيرة (رأس واحد) للمساعدة في تصحيح الأخطاء المطبوعة في C ++ 11 و Rolffer.
جربه في برنامج التحويل البرمجي!
محتويات
مع Icecream ، فحص التنفيذ:
auto my_function ( int i, double d) -> void
{
std::cout << " 1 " << std::endl;
if (condition)
std::cout << " 2 " << std::endl;
else
std::cout << " 3 " << std::endl;
}يمكن ترميزها بدلاً من ذلك:
auto my_function ( int i, double d) -> void
{
IC ();
if (condition)
IC ();
else
IC ();
}وسوف تطبع شيئًا مثل:
ic| test.cpp:34 in "void my_function(int, double)"
ic| test.cpp:36 in "void my_function(int, double)"
أيضا ، أي فحص متغير مثل:
std::cout << " a: " << a
<< " , b: " << b
<< " , sum(a, b): " << sum(a, b)
<< std::endl;يمكن تبسيطها إلى:
IC (a, b, sum(a, b));وسوف يطبعون:
ic| a: 7, b: 2, sum(a, b): 9
يمكننا أيضًا فحص البيانات التي تتدفق من خلال خط أنابيب عرض المدى (كل من نطاقات STL و Range-V3) ، عن طريق إدخال دالة IC_V() عند نقطة الاهتمام:
auto rv = std::vector< int >{ 1 , 0 , 2 , 3 , 0 , 4 , 5 }
| vws::split( 0 )
| IC_V()
| vws::enumerate; لذلك عندما نكرر على rv ، سنرى الطباعة:
ic| range_view_63:16[0]: [1]
ic| range_view_63:16[1]: [2, 3]
ic| range_view_63:16[2]: [4, 5]
هذه المكتبة مستوحاة من مكتبة Python Icecream الأصلية.
Icecream-CPP هو ملف واحد ، رأس فقط مكتبة ، ويحتوي على STL كاعتمادها الوحيد. الطريقة الأكثر إلحاحًا لاستخدامها هي مجرد نسخ icecream.hpp رأس في مشروعك.
لتثبيت نظام تكنولوجيا المعلومات بشكل صحيح ، جنبًا إلى جنب مع ملفات مشروع CMake ، قم بتشغيل هذه الأوامر في دليل جذر مشروع ICECREAM-CPP:
mkdir build
cd build
cmake ..
cmake --install .في حالة استخدام NIX ، يمكن تضمين Icecream-CPP كمدخلات رقائق مثل
inputs . icecream-cpp . url = "github:renatoGarcia/icecream-cpp" ; يحدد تقشر Icecream-CPP تراكبًا ، بحيث يمكن استخدامه عند استيراد nixpkgs :
import nixpkgs {
system = "x86_64-linux" ;
overlays = [
icecream-cpp . overlays . default
] ;
} القيام بذلك ، سيتم إضافة اشتقاق icecream-cpp إلى مجموعة سمات nixpkgs .
مثال عملي على كيفية استخدام Icecream-CPP في مشروع Flake موجود هنا.
الإصدارات التي تم إصدارها متوفرة على كونان أيضًا:
conan install icecream-cpp/0.3.1@إذا كنت تستخدم cmake:
find_package (IcecreamCpp)
include_directories ( ${IcecreamCpp_INCLUDE_DIRS} )سيضيف الدليل المثبت ضمن قائمة المسارات.
بعد تضمين رأس icecream.hpp في ملف مصدر:
# include < icecream.hpp > ستتوفر جميع وظائف مكتبة Icecream-CPP بواسطة وظائف IC و IC_A و IC_V ؛ جنبا إلى جنب مع نظيراتها IC_F و IC_FA و IC_FV ؛ التي تتصرف نفس الشيء ولكنها تقبل سلسلة تنسيق الإخراج كوسيطة لها الأولى.
IC هي أبسط وظائف Icecream. إذا تم استدعاؤه بدون وسيطات ، فسيقوم بطباعة البادئة واسم الملف المصدر ورقم السطر الحالي وتوقيع الوظيفة الحالية. الرمز:
auto my_function ( int foo, double bar) -> void
{
// ...
IC ();
// ...
}سوف يطبع:
ic| test.cpp:34 in "void my_function(int, double)"
إذا تم استدعاؤها مع الوسائط ، فسيقوم بطباعة البادئة ، وأسماء الوسائط هذه ، وقيمها. الرمز:
auto v0 = std::vector< int >{ 1 , 2 , 3 };
auto s0 = std::string{ " bla " };
IC (v0, s0, 3.14 );سوف يطبع:
ic| v0: [1, 2, 3], s0: "bla", 3.14: 3.14
يتصرف IC_F المتغير مثل وظيفة IC ، لكنه يقبل سلسلة تنسيق الإخراج كوسيطة أولى.
لطباعة البيانات التي تتدفق من خلال خط أنابيب طرق عرض المدى (كل من نطاقات STL و Range-V3) ، نستخدم وظيفة IC_V ، والتي ستطبع أي إدخال تتلقاها من العرض السابق. نظرًا لأن وظيفة IC_V موجودة ضمن خط أنابيب مشاهدات النطاق ، ستتم الطباعة بتكاسل ، بينما يتم إنشاء كل عنصر. على سبيل المثال:
namespace vws = std::views;
auto v0 = vws::iota( ' a ' ) | vws::enumerate | IC_V() | vws::take( 3 );
for ( auto e : v0)
{
// ...
} في هذا الرمز ، لن يتم طباعة أي شيء عند إنشاء v0 ، فقط عند التكرار عليه. في كل تكرار في خط for ، سيتم طباعة سطر واحد ، حتى يكون لدينا الإخراج:
ic| range_view_61:53[0]: (0, 'a')
ic| range_view_61:53[1]: (1, 'b')
ic| range_view_61:53[2]: (2, 'c')
ملحوظة
سيحاول Icecream-CPP اكتشاف ما إذا كانت مكتبة Range-V3 مثبتة ، وإذا كان الأمر كذلك ، فسيتم تمكينها تلقائيًا. عند استخدام C ++ 11 و C ++ 14 ، هناك فرصة للحصول على المدى V3 في النظام ، ولكن لا يجد Icecream ذلك. للتأكد من تمكين الدعم للمدى V3 ، فقط حدد Macro ICECREAM_RANGE_V3 قبل تضمين icecream.hpp header
تحتوي وظيفة IC_V على معلمتين اختياريتين ، IC_V(name, projection) .
الاسم المتغير المستخدم في العرض عند الطباعة. تخطيط الطباعة هو: <name>[<idx>]: <value> . إذا لم يتم استخدام معلمة الاسم ، فإن القيمة الافتراضية لـ <name> هي range_view_<source_location> .
الرمز:
vws::iota ( ' a ' ) | vws::enumerate | IC_V( " foo " ) | vws::take( 2 );عندما يتم توجيهه سوف يطبع:
ic| foo[0]: (0, 'a')
ic| foo[1]: (1, 'b')
قابلة للتطبيق سيتلقى إدخال العناصر من العرض السابق ويجب إرجاع الكائن الفعلي المطلوب طباعته.
الرمز:
vws::iota ( ' a ' ) | vws::enumerate | IC_V([]( auto e){ return std::get< 1 >(e);}) | vws::take( 2 );عندما يتم توجيهه سوف يطبع:
ic| range_view_61:53[0]: 'a'
ic| range_view_61:53[1]: 'b'
ملحوظة
ستظل وظيفة IC_V تُحيل إلى العرض التالي عنصر إدخال غير متغير ، تمامًا كما تم استلامه من العرض السابق. لا يوجد أي إجراء تقوم به وظيفة projection سيكون له أي تأثير على ذلك.
يحتوي IC_FV المتغير على نفس سلوك وظيفة IC_V ، ولكنه يقبل سلسلة تنسيق الإخراج كوسيطة لها الأولى.
باستثناء ما تم استدعاؤه مع وسيطة واحدة بالضبط ، ستعيد دالة IC tuple مع جميع وسيطات الإدخال الخاصة بها. إذا تم استدعاؤه بحجة واحدة ، فسوف يعيد الحجة نفسها.
يتم ذلك بهذه الطريقة حتى تتمكن من استخدام IC لتفقد وسيطة الوظيفة في نقطة الاتصال ، مع عدم وجود تغيير رمز إضافي. في الكود:
my_function (IC(MyClass{})); سيتم إعادة توجيه كائن MyClass إلى my_function تمامًا كما لو كانت وظيفة IC لم تكن موجودة. سيستمر my_function في تلقي مرجع RValue إلى كائن MyClass .
ومع ذلك ، فإن هذا النهج ليس عمليًا عندما يكون للوظيفة العديد من الحجج. على الكود:
my_function (IC(a), IC(b), IC(c), IC(d)); إلى جانب الكتابة أربعة أضعاف وظيفة IC ، سيتم تقسيم المخرجات المطبوعة في أربعة خطوط متميزة. شيء مثل:
ic| a: 1
ic| b: 2
ic| c: 3
ic| d: 4
لسوء الحظ ، فقط لف جميع الحجج الأربع في مكالمة IC واحدة لن يعمل أيضًا. ستكون القيمة التي تم إرجاعها std:::tuple مع (a, b, c, d) ويتوقع my_function أربع وسيطات.
للتغلب على ذلك ، هناك وظيفة IC_A . يتصرف IC_A تمامًا مثل وظيفة IC ، ولكنه يتلقى قابلاً للاستدعاء كوسيطة أولى ، وسيسميها باستخدام جميع الوسائط التالية ، وطباعةها جميعًا قبل ذلك. يمكن إعادة كتابة رمز المثال السابق على النحو التالي:
IC_A (my_function, a, b, c, d);وهذه المرة سوف تطبع:
ic| a: 1, b: 2, c: 3, d: 4
ستعيد وظيفة IC_A نفس القيمة التي يتم إرجاعها بواسطة Callable. الرمز:
auto mc = std::make_unique<MyClass>();
auto r = IC_A(mc->my_function, a, b);يتصرف تمامًا مثل:
auto mc = std::make_unique<MyClass>();
auto r = mc-> my_function (a, b); ولكن سوف تطبع قيم a و b
يتصرف IC_FA المتغير مثل وظيفة IC_A ، لكنه يقبل سلسلة تنسيق الإخراج كوسيطة الأولى ، حتى قبل الوسيطة القابلة للاستدعاء.
من الممكن تكوين كيفية تنسيق القيمة أثناء الطباعة. الرمز التالي:
auto a = int { 42 };
auto b = int { 20 };
IC_F ( " #X " , a, b);سوف يطبع:
ic| a: 0X2A, b: 0X14
عند استخدام متغير IC_F بدلاً من Plain IC functio. سيتم الحصول على نتيجة مماثلة في حالة استخدام IC_FA و IC_FV بدلاً من IC_A و IC_V على التوالي.
عند استخدام متغيرات دالة التنسيق ( IC_F و IC_FA ) ، سيتم تطبيق نفس سلسلة التنسيق افتراضيًا على جميع الوسائط. قد تكون هذه مشكلة إذا كنا نرغب في الحصول على حجج ذات تنسيق متميز ، أو إذا كانت الوسيطات لها أنواع متعددة ذات بناء جملة غير صالحة للطرفين. لذلك ، لتعيين سلسلة تنسيق مميزة على وسيطة محددة يمكننا لفها مع وظيفة IC_ . الرمز:
auto a = int { 42 };
auto b = int { 20 };
IC_F ( " #X " , a, IC_( " d " , b));سوف يطبع:
ic| a: 0X2A, b: 20
يمكن استخدام وظيفة IC_ ضمن وظيفة IC (أو IC_A ) العادية أيضًا:
auto a = int { 42 };
auto b = int { 20 };
IC (IC_( " #x " , a), b);سوف يطبع:
ic| a: 0x2a, b: 20
الوسيطة الأخيرة في استدعاء دالة IC_ هي تلك التي سيتم طباعتها ، سيتم تحويل جميع الوسائط الأخرى التي تأتي قبل الأخير إلى سلسلة باستخدام وظيفة to_string وتسلسلها كسلسلة التنسيق الناتجة.
auto a = float { 1.234 };
auto width = int { 7 };
IC (IC_( " *< " ,width, " .3 " , a)); سوف يكون لها نتيجة سلسلة تنسيق "*<7.3" ، وسوف تطبع:
ic| a: 1.23***
فقط للاكتمال في الأمثلة ، سيكون استخدام IC_FA و IC_FV :
IC_FA ( " #x " , my_function, 10 , 20 );
auto rv0 = vws::iota( 0 ) | IC_FV( " [::2]:#x " , " bar " ) | vws::take( 5 );هذا سوف يطبع:
ic| 10: 0xa, 20: 0x14
وعند التكرار على rv0 :
ic| bar[0]: 0
ic| bar[2]: 0x2
ic| bar[4]: 0x4
إلى IC_F و IC_FA ، تعتمد مواصفات بناء الجملة لسلاسل التنسيق على كلاهما على النوع T المطبوع ، وفي استراتيجية الطباعة لهذا النوع المستخدمة بواسطة Icecream.
إلى IC_FV ، بناء جملة التنسيق إذا كان نفس سلسلة تنسيق النطاق.
تشفير الأحرف في C ++ هو فوضوي.
يتم تعريف سلاسل char8_t و char16_t و char32_t بشكل جيد. إنهم قادرون ، ويحملون وحدات رمز Unicode من 8 و 16 و 32 بت على التوالي ، ويتم ترميزها في UTF-8 و UTF-16 و UTF-32 على التوالي.
تحتوي سلاسل char على حجم بتات وحدة الكود المحددة جيدًا (المقدمة بواسطة CHAR_BIT ، عادة 8 بتات) ، ولكن لا توجد متطلبات حول ترميزها.
لا تحتوي سلاسل wchar_t على حجم وحدة رمز محددة جيدًا ، ولا أي متطلبات حول ترميزها.
في رمز مثل هذا:
auto const str = std::string{ " foo " };
std::cout << str; سيكون لدينا ثلاث نقاط ترميز الأحرف ذات الاهتمام. في أول واحد ، قبل التجميع ، سيكون هذا الرمز في ملف مصدر في "تشفير مصدر" غير محدد. في نقطة الاهتمام الثانية ، سيكون للثنائي المترجم سلسلة "FOO" المحفوظة في "تنفيذ" غير محدد. أخيرًا في النقطة الثالثة ، سيتم إعادة توجيه دفق البايت "Foo" الذي تلقاه std::cout إلى النظام ، والذي يتوقع تشفير الدفق في "ترميز الإخراج" غير محدد أيضًا.
من بين نقاط الاهتمام الثلاثة لترميز الأحرف ، كل من "ترميز التنفيذ" و "ترميز الإخراج" لهما تأثير في العمل الداخلي لـ Icecream-CPP ، ولا توجد طريقة لمعرفة ما هو الترميز المستخدم في كل منهما. في مواجهة عدم اليقين هذا ، تقدم الاستراتيجية المعتمدة وظيفة ترميز الافتراضي المعقولة ، والتي ستحاول تحويل البيانات إلى الترميز الأيمن ، والسماح للمستخدم باستخدام تنفيذه الخاص عند الحاجة.
باستثناء أنواع السلسلة الواسعة والوحدة (التي تمت مناقشتها أدناه) ، عند طباعة أي نوع آخر ، سيكون لدينا بيانات نصي متسلسلة في "تنفيذ ترميز". قد يكون أو لا يكون أو لا يكون "ترميز التنفيذ" هو نفسه "ترميز الإخراج" ، وهذا هو الترميز المتوقع من خلال الإخراج المكون. ولهذا السبب ، قبل أن نرسل تلك البيانات إلى الإخراج ، يجب أن ننقلها للتأكد من أننا في "ترميز الإخراج". تحقيقًا لهذه الغاية ، قبل توصيل البيانات النصية إلى الإخراج ، نرسلها إلى وظيفة Output_transcoder التي تم تكوينها ، والتي يجب أن تتأكد من ترميزها في "الترميز" الصحيح.
عند طباعة أنواع السلسلة الواسعة والوحدة ، نحتاج إلى الحصول على مستوى ترميز آخر ، لأنه من الممكن أن تكون البيانات النصية في حرف مميز تشفير من "ترميز التنفيذ" المتوقع. ولهذا السبب ، يتم تطبيق منطق إضافي للتأكد من أن الأوتار في "ترميز التنفيذ" قبل أن نرسلها إلى الإخراج. تمت مناقشة هذا في الأوتار الواسعة ، وأقسام سلاسل يونيكود.
يعمل نظام تكوين Icecream-CPP "طبقة حسب النطاق". على مستوى الأساس لدينا كائن IC_CONFIG العالمي. يتم مشاركة هذه الحالة العالمية من خلال برنامج التشغيل بالكامل ، كما هو متوقع من متغير عالمي. يتم إنشاؤه مع جميع خيارات التكوين في قيمها الافتراضية ، ويتم رؤية أي تغيير بسهولة من قبل البرنامج بأكمله.
في أي نقطة من الكود ، يمكننا إنشاء طبقة تكوين جديدة في النطاق الحالي عن طريق إنشاء متغير جديد IC_CONFIG ، واتصال الماكرو IC_CONFIG_SCOPE() . جميع خيارات التكوين لهذا المثيل الجديد ستكون في حالة "إلغاء تعيين" افتراضيًا ، وسيتم تفويض أي طلب إلى قيمة خيار لم يتم تعيينه بعد إلى الوالد. سوف يرتفع هذا الطلب على السلسلة الأصلية حتى يتم تعيين الإجابات على الخيار الأول.
يتم تعيين جميع خيارات التكوين باستخدام أساليب الوصول لكائن IC_CONFIG ، ويمكن ربطها:
IC_CONFIG
.prefix( " ic: " )
.show_c_string( false )
.line_wrap_width( 70 ); IC_CONFIG هو مجرد متغير منتظم مع اسم مضحك لجعل التصادم غير مرجح للغاية. عند استدعاء أي ماكرو IC*(...) ، فسيختار مثيل IC_CONFIG في SCOPE عن طريق إجراء بحث غير مؤهل للاسم ، باستخدام نفس القواعد المطبقة على أي متغير عادي آخر.
لتلخيص كل ما سبق ، في الكود:
auto my_function () -> void
{
IC_CONFIG. line_wrap_width ( 20 );
IC_CONFIG_SCOPE ();
IC_CONFIG. context_delimiter ( " | " );
IC_CONFIG. show_c_string ( true );
{
IC_CONFIG_SCOPE ();
IC_CONFIG. show_c_string ( false );
// A
}
// B
} في السطر A ، ستكون قيمة IC_CONFIG 'S line_wrap_width ، context_delimiter ، و show_c_string على التوالي: 20 ، "|" false .
بعد إغلاق كتلة نطاق الأعمق ، في السطر B ، ستكون قيمة IC_CONFIG من line_wrap_width ، context_delimiter ، و show_c_string على التوالي: 20 ، "|" true .
عمليات القراءة والكتابة على كائنات IC_CONFIG آمنة مؤشر ترابط.
ملحوظة
أي تعديل في IC_CONFIG ، بخلاف المثيل العالمي ، سيظهر فقط في النطاق الحالي. نتيجة لذلك ، لن تنتشر هذه التعديلات إلى نطاق أي وظيفة تسمى.
تمكين أو تعطيل إخراج الماكرو IC(...) ، التمكين الافتراضي.
auto is_enabled () const -> bool; auto enable () -> Config&;
auto disable () -> Config&;الرمز:
IC ( 1 );
IC_CONFIG.disable();
IC ( 2 );
IC_CONFIG.enable();
IC ( 3 );سوف يطبع:
ic| 1: 1
ic| 3: 3
مجموعات حيث سيتم طباعة البيانات النصية المسلسل. بشكل افتراضي ، سيتم طباعة البيانات على إخراج الخطأ القياسي ، مثل std::cerr .
auto output () const -> std::function<void(std::string const &)>; template < typename T>
auto output (T&& t) -> Config&; حيث يمكن أن يكون النوع T أي من:
std::ostream .push_back(char) .*it = 'c'على سبيل المثال ، الرمز:
auto str = std::string{};
IC_CONFIG.output(str);
IC ( 1 , 2 ); سيقوم بطباعة الإخراج "ic| 1: 1, 2: 2n" على سلسلة str .
تحذير
لن يأخذ Icecream-CPP ملكية الوسيطة t ، لذلك يجب على المستخدم توخي الحذر للتأكد من أنها على قيد الحياة.
وظيفة تنشئ النص الذي سيتم طباعته قبل كل إخراج.
auto prefix () const -> std::function<std::string()>; template < typename ... Ts>
auto prefix (Ts&& ...values) -> Config&; حيث يمكن أن تكون أنواع Ts أي من:
T() -> U ، حيث U حمولة زائدة من operator<<(ostream&, U) .ستكون البادئة المطبوعة بمثابة تسلسل لجميع هذه العناصر.
الرمز:
IC_CONFIG.prefix( " icecream| " );
IC ( 1 );
IC_CONFIG.prefix([]{ return 42 ;}, " - " );
IC ( 2 );
IC_CONFIG.prefix( " thread " , std::this_thread::get_id, " | " );
IC ( 3 );سوف يطبع:
icecream| 1: 1
42- 2: 2
thread 1 | 3: 3
الضوابط إذا كان ينبغي تفسير متغير char* على أنه سلسلة C الممنوحة الفارغة ( true ) أو مؤشر إلى char ( false ). القيمة الافتراضية true .
auto show_c_string () const -> bool; auto show_c_string ( bool value) -> Config&;الرمز:
char const * flavor = " mango " ;
IC_CONFIG.show_c_string( true );
IC (flavor);
IC_CONFIG.show_c_string( false );
IC (flavor);سوف يطبع:
ic| flavor: "mango";
ic| flavor: 0x55587b6f5410
الوظيفة التي تُقلِّل ترميز سلسلة wchar_t ، من نظام محدد للترميز إلى سلسلة char في النظام "ترميز التنفيذ".
auto wide_string_transcoder () const -> std::function<std::string( wchar_t const *, std:: size_t )>; auto wide_string_transcoder (std::function<std::string( wchar_t const *, std:: size_t )> transcoder) -> Config&;
auto wide_string_transcoder (std::function<std::string(std::wstring_view)> transcoder) -> Config&;لا يوجد أي ضمان بأن سلسلة الإدخال ستنتهي على مُنمِّع فارغ (هذا هو الدلالي الفعلي لـ String_View) ، لذلك يجب على المستخدم ملاحظة قيمة حجم سلسلة الإدخال.
سيقوم التنفيذ الافتراضي بالتحقق مما إذا تم تعيين لغة C على قيمة أخرى غير "C" أو "Posix". إذا كانت الإجابة بنعم ، فسيتم إعادة توجيه المدخلات إلى وظيفة STD :: WCRTOMB. خلاف ذلك ، سوف نفترض أن الإدخال يتم ترميزه (UTF-16 أو UTF-32 ، وفقًا لحجم البايت لـ wchar_t ) ، وتجاوزه إلى UTF-8.
الوظيفة التي تُقلِّل ترميز سلسلة char32_t ، من ترميز UTF-32 إلى سلسلة char في النظام "تنفيذ الترميز".
auto unicode_transcoder () const -> std::function<std::string( char32_t const *, std:: size_t )>; auto unicode_transcoder (std::function<std::string( char32_t const *, std:: size_t )> transcoder) -> Config&;
auto unicode_transcoder (std::function<std::string(std::u32string_view)> transcoder) -> Config&;لا يوجد أي ضمان بأن سلسلة الإدخال ستنتهي على مُنمِّع فارغ (هذا هو الدلالي الفعلي لـ String_View) ، لذلك يجب على المستخدم ملاحظة قيمة حجم سلسلة الإدخال.
سيقوم التنفيذ الافتراضي بالتحقق من تحديد موقع C على قيمة أخرى غير "C" أو "Posix". إذا كانت الإجابة بنعم ، فسيتم إعادة توجيه المدخلات إلى وظيفة std :: c32rtomb. خلاف ذلك ، سيتم نقله فقط إلى UTF-8.
سيتم استخدام هذه الوظيفة لتنقل كل سلاسل char8_t و char16_t و char32_t . عند نقل خيوط char8_t و char16_t ، سيتم تحويلها أولاً إلى سلسلة char32_t ، قبل إرسالها كمدخل لهذه الوظيفة.
الوظيفة التي تُقلِّل ترميز سلسلة char ، من النظام "تنفيذ ترميز" إلى سلسلة char في النظام "ترميز الإخراج" ، كما هو متوقع بواسطة الإخراج المكون.
auto output_transcoder () const -> std::function<std::string( char const *, std:: size_t )>; auto output_transcoder (std::function<std::string( char const *, std:: size_t )> transcoder) -> Config&;
auto output_transcoder (std::function<std::string(std::string_view)> transcoder) -> Config&;لا يوجد أي ضمان بأن سلسلة الإدخال ستنتهي على مُنمِّع فارغ (هذا هو الدلالي الفعلي لـ String_View) ، لذلك يجب على المستخدم ملاحظة قيمة حجم سلسلة الإدخال.
يفترض التنفيذ الافتراضي أن "ترميز التنفيذ" هو نفسه "ترميز الإخراج" ، وسيعيد فقط إدخالًا غير متغير.
الحد الأقصى لعدد الأحرف قبل كسر الإخراج على خطوط متعددة. القيمة الافتراضية 70 .
auto line_wrap_width () const -> std::size_t; auto line_wrap_width (std:: size_t value) -> Config&; إذا كان يجب طباعة السياق (اسم المصدر ورقم السطر واسم الوظيفة) حتى عند طباعة المتغيرات. القيمة الافتراضية false .
auto include_context () const -> bool; auto include_context ( bool value) -> Config&; السلسلة التي تفصل بين نص السياق عن قيم المتغيرات. القيمة الافتراضية هي "- " .
auto context_delimiter () const -> std::string; auto context_delimiter (std::string const & value) -> Config&; من أجل أن تكون قابلة للطباعة ، يجب أن يفي النوع T بأحد الاستراتيجيات الموضحة في الأقسام التالية. إذا حدث أن يتم استيفاء استراتيجيات متعددة ، فسيتم اختيار الاستراتيجيات ذات الأسبقية العليا.
الاستراتيجية ذات الأسبقية الأعلى هي استخدام I/O القائم على دفق STL. وبالتالي ، عند طباعة كائن من النوع T ، إذا كان هناك operator<<(ostream&, T) ، فسيتم استخدامه.
ج السلاسل غامضة. هل يجب تفسير متغير char* foo على أنه مؤشر إلى char واحد أو كسلسلة مطلقة على الفرق؟ وبالمثل ، هل يتغير char bar[] مجموعة من الأحرف المفردة أو سلسلة من إنهاء الفرق؟ هل char baz[3] صفيف مع ثلاثة أحرف واحدة أم أنها سلسلة من الحجم اثنين بالإضافة إلى '