سؤال

لقد قمت بإنشاء فئة كروموسوم والتي انتهى بها الأمر إلى كونها مجرد غلاف للمتجه باستخدام عامل تشغيل ostream، لذلك قررت أن أكتب ناقل typedef بدلاً من ذلك.ومع ذلك، أواجه مشكلة مع مشغل ostream القالب...هل هذه هي أفضل طريقة للقيام بذلك؟(لقد رأيت بعض الأساليب وفشلت في تشغيل أي منها)

template<typename G>
class Chromosome {
 public:
  typedef typename std::vector<G> type;
  typedef typename std::pair<type *,type *> ptr_pair;
};

template<typename G> //line 19 below:
std::ostream& operator<<(std::ostream& os, const Chromosome<G>::type& chromosome) {
  for(auto iter = chromosome.begin(); iter != chromosome.end(); ++iter)
    std::cout << *iter;
  return os;
}

في الوقت الحالي الخطأ الذي أتلقاه هو:

chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token

هتافات.

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

المحلول

لسوء الحظ، لا توجد طريقة نظيفة للقيام بذلك لأن المترجم لا يمكنه استنتاج نوع الملف G من اعلان الدالة

template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);

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

template <typename G> class Chromosome {
public:
    typedef std::vector<G> type; // No typename needed here, BTW
};

template <> class Chromosome<int> {
public:
    typedef std::vector<double> type;
};

الآن، ماذا سيحدث لو فعلت هذا؟

vector<double> v;
cout << v << endl;

لا يستطيع المترجم معرفة ما إذا كان G يكون double أو int في هذه الحالة، لأن كليهما Chromosome<int> و Chromosome<double> يملك vector<double> كنوعهم المتداخل.

لإصلاح ذلك، سيتعين عليك استخدام النوع بشكل صريح vector<G> كالحجة:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);

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

نصائح أخرى

العضو typedef type هو اسم تابع:معناها يعتمد على معلمة القالب G.تحتاج إلى استخدام أ typename لنقول للمترجم ذلك type يسمي نوعاً:

const typename Chromosome<G>::type&

للحصول على الشرح الكامل، فكر في قراءة مقالة الأسئلة الشائعة حول Stack Overflow C++، مكان وضع "القالب" و"اسم النوع" على الأسماء التابعة.

كما يشير @templatetypedef في التعليقات، في حين أن هذا سيمكن من تجميع التعليمات البرمجية، إلا أنه لن "يعمل" للسماح لك بإدراج رمز std::vector<G> في std::ostream لأن type هو في سياق غير استنتاجي.

أسهل طريقة للإعلان عن التحميل الزائد والحصول على السلوك المتوقع هي الاستخدام std::vector<G> مباشرة كنوع الوسيطة:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top