ما هي أمثلة قائمة التهيئة الجشع التي تكمن في المكتبة القياسية؟

StackOverflow https://stackoverflow.com/questions/19847960

سؤال

منذ C ++ 11 ، حاويات المكتبة القياسية و std::string لديك البنائين يأخذون قائمة التهيئة. هذا المُنشئ له الأسبقية على المُنشئين الآخرين (حتى ، كما أشار @Johannesschaub-LITB في التعليقات ، حتى تجاهل معايير "أفضل مباراة" أخرى). هذا يؤدي إلى بعض المزالق المعروفة عند تحويل جميع الأقواس () أشكال من البنائين إلى إصداراتهم المستعدة {}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 copies of 'C'
}

لم أتمكن من العثور على المثال الثالث على هذا الموقع ، وظهر الشيء في الصالةu003CC++> الدردشة (في مناقشة مع Rightfold و abyx و @jerrycoffin) ، والشيء المثير للدهشة إلى حد ما هو تحويل std::string مُنشئ يأخذ عدًا وشخصية للاستخدام {} بدلاً من (), ، يغير معناها من n نسخ من الشخصية إلى n-الطابع (عادة من جدول ASCII) تليها الحرف الآخر.

لا يتم القبض على هذا من خلال حظر الدعامة المعتادة على تضييق التحويلات ، لأن 65 هو تعبير مستمر يمكن تمثيله كـ char وسيحتفظ بقيمته الأصلية عند تحويله إلى int (§8.5.4/7 ، الرصاصة 4) (شكرًا إلى jerrycoffin).

سؤال: هل هناك المزيد من الأمثلة التي تتربص في المكتبة القياسية حيث تحويل أ () مُنشئ نمط ل {} الأناقة ، هل يتطابق مع مُنشئ قائمة التهيئة؟

هل كانت مفيدة؟

المحلول

أفترض ، مع الأمثلة الخاصة بك std::vector<int> و std::string كنت تقصد أيضًا تغطية الحاويات الأخرى ، على سبيل المثال ، std::list<int>, std::deque<int>, ، وما إلى ذلك التي لها نفس المشكلة ، من الواضح ، كما std::vector<int>. وبالمثل ، فإن int ليس النوع الوحيد كما ينطبق أيضًا char, short, long وهم unsigned الإصدار (ربما بعض الأنواع المتكاملة الأخرى أيضًا).

أعتقد أن هناك أيضا std::valarray<T> لكنني لست متأكدًا مما إذا T يسمح ليكون نوع متكامل. في الواقع ، أعتقد أن هذه دلالات مختلفة:

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};

هناك عدد قليل من قوالب فئة C ++ القياسية الأخرى التي تأخذ std::initializer_list<T> كحجة ولكني لا أعتقد أن أيًا من هذه الأشياء لديه مُنشئ زائد سيتم استخدامه عند استخدام الأقواس بدلاً من الأقواس.

نصائح أخرى

مجرد البحث عن حدوث initializer_list.

  • جميع التسلسلات ، لديهم منشئون مثل المتجه:

    • ديك
    • Dynarray
    • forward_list
    • قائمة
    • المتجه
  • فالاراي

  • basic_string

  • مجموعات غير مرتبة ، هناك مُنشئ يأخذ عددًا صحيحًا لتحديد عدد الجرافات الأولي.

    • unordered_set
    • unordered_multiset

أعتقد أن هذا كله.

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> f (3);
    std::unordered_set<int> g {3};
    std::cout << f.size() << "/" << g.size() << std::endl; // prints 0/1.
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top