c++ صفحات - فئة القالب مع حاوية القالب




بلوجر amp (3)

كيف يمكنني تعريف فئة القالب (المحول) مع حاويات مختلفة كوسائط القالب؟ على سبيل المثال ، أحتاج إلى إعلان الفصل الدراسي:

template<typename T, typename Container>
class MyMultibyteString
{
    Container buffer;
    ...
};

وأريده أن يستند إلى متجه. كيفية جعلها محددة بدقة؟ (لمنع أي شخص من كتابة مثل هذا الإعلان MyMultibyteString<int, vector<char>> ).

علاوة على ذلك ، كيفية تنفيذ هذا البناء:

MyMultibyteString<int, std::vector> mbs;

دون تمرير وسيطة القالب إلى الحاوية.


Answers

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

template<template <typename... Args> class Container,typename... Types>
class Test
{
    public:
    Container<Types...> test;

};
int main()
{
  Test<std::vector,int> t;
  Test<std::set,std::string> p;
  return 0;
}

يجب عليك استخدام معلمات قالب القالب :

template<typename T, template <typename, typename> class Container>
//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MyMultibyteString
{
    Container<T, std::allocator<T>> buffer;
    // ...
};

هذا من شأنه أن يسمح لك بالكتابة:

MyMultibyteString<int, std::vector> mbs;

هنا مثال حي مباشر . طريقة بديلة لكتابة ما سبق يمكن أن تكون:

template<typename T,
    template <typename, typename = std::allocator<T>> class Container>
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MyMultibyteString
{
    Container<T> buffer; // <== No more need to specify the second argument here
    // ...
};

وهنا هو المثال الحي المقابل.

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

على سبيل المثال ، يقبل std::vector قالب الفئة معلمتين قالب (نوع عنصر ونوع المخصص) ، على الرغم من أن الثاني يحتوي على القيمة الافتراضية std::allocator<T> . لهذا السبب ، لا يمكنك كتابة:

template<typename T, template <typename> class Container>
//                             ^^^^^^^^
//                             Notice: just one template parameter declared!
class MyMultibyteString
{
    Container<T> buffer;
    // ...
};

// ...

MyMultibyteString<int, std::vector> mbs; // ERROR!
//                     ^^^^^^^^^^^
//                     The std::vector class template accepts *two*
//                     template parameters (even though the second
//                     one has a default argument)

هذا يعني أنك لن تتمكن من كتابة قالب فئة واحد يمكنه قبول كل من std::set و std::vector كمعلمة قالب قالب ، لأنه على عكس std::vector ، يقبل قالب فئة std::set معلمات قالب .


القيام بذلك بشكل عام سيكون صعبا للغاية.

أولاً ، ضع في اعتبارك std::vector<T, Allocator=std::allocator<T>> ، ودعنا نقول إن فنانك يقوم بتحويل T->U ليس لدينا فقط لتعيين وسيطة النوع الأول ، ولكن في الحقيقة يجب علينا استخدام Allocator<T>::rebind<U> للحصول على الثاني. هذا يعني أننا نحتاج إلى معرفة أن الحجة الثانية عبارة عن مُخصص في المقام الأول ... أو نحتاج إلى بعض الأجهزة للتحقق من وجود نموذج عضو rebind واستخدامه.

بعد ذلك ، ضع في اعتبارك std::array<T, N> . هنا نحن بحاجة إلى معرفة ينبغي نسخ الحجة الثانية حرفيا إلى std::array<U, N> . ربما يمكن أن نأخذ معلمات غير نوع دون تغيير ، معلمات نوع rebind التي لها قالب عضو rebind ، واستبدال T الحرفية مع U ؟

الآن ، std::map<Key, T, Compare=std::less<Key>, Allocator=std::allocator<std::pair<Key,T>>> . يجب أن نأخذ Key دون تغيير ، استبدال T مع U ، أخذ Compare دون تغيير و rebind Allocator إلى std::allocator<std::pair<Key, U>> . هذا أكثر تعقيدًا بعض الشيء.

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







c++ templates stl containers