سؤال

لدي فئة زائر تشبه هذا:

struct Visitor 
{
    template <typename T>
    void operator()(T t)
    {
        ...
    }

    void operator()(bool b)
    {
        ...
    }
};

بوضوح، operator()(bool b) يهدف إلى أن تكون متخصصة في وظيفة القالب السابقة.

ومع ذلك، فإنه لا يملك template<> بناء الجملة الذي اعتدت على رؤيته قبل ذلك، يعلن هذا كتخصص قالب. لكنه يترجم.

هل هذا آمن؟ هل هذا صحيح؟

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

المحلول

الكود الخاص بك ليس تخصصا قوالب، بل وظيفة غير قالب. هناك بعض الاختلافات هناك. سيستغرق المشغل غير القالب () الأسبقية على إصدار قالب (للحصول على تطابق دقيق، ولكن لن يتم إجراء تحويلات من النوع موجودا هناك) ولكن لا يزال بإمكانك إجبار الوظيفة القيب عليها لتكون تسمى:

class Visitor
{
public: // corrected as pointed by stefanB, thanks
   template <typename T>
   void operator()( T data ) {
      std::cout << "generic template" << std::endl;
   }
   void operator()( bool data ) {
      std::cout << "regular member function" << std::endl;
   }
};
template <> // Corrected: specialization is a new definition, not a declaration, thanks again stefanB 
void Visitor::operator()( int data ) {
   std::cout << "specialization" << std::endl;
}
int main()
{
   Visitor v;
   v( 5 ); // specialization
   v( true ); // regular member function
   v.operator()<bool>( true ); // generic template even if there is a non-templated overload
   // operator() must be specified there (signature of the method) for the compiler to 
   //    detect what part is a template. You cannot use <> right after a variable name
}

في التعليمات البرمجية الخاصة بك ليس هناك الكثير من الفرق، ولكن إذا كان الرمز الخاص بك يحتاج إلى تمرير نوع المعلمة القالب، فستحصل على تسلية:

template <typename T>
T g() { 
   return T();
}
template <>
int g() {
   return 0;
}
int g() {
   return 1;
}
int main()
{
   g<double>(); // return 0.0
   g<int>(); // return 0
   g(); // return 1 -- non-templated functions take precedence over templated ones
}

نصائح أخرى

ما لديك هنا هو التحميل الزائد الوظيفي؛ للحصول على تخصص القالب، تحتاج بالفعل template <> بناء الجملة. ومع ذلك، يجب أن تدرك أن هذين مناهضين، حتى لو كانت قد تبدو متطابقة، فهي مختلفة بمهارة، وحتى قد تضيع التحويل البرمجي عند اختيار الوظيفة الصحيحة للاتصال. سرد جميع الحالات المحتملة ستكون طويلة جدا عن هذه الإجابة، ولكن قد ترغب في التحقق عشبة سوتر gotw # 49 حول هذا الموضوع.

أوه، سوف يترجم. هذا فقط لن يكون وظيفة القالب. سيكون لديك وظيفة غير قالب منتظمة بدلا من تخصص القالب.

انها آمنة، وعلى الأرجح في الواقع ما تريد كذلك. يتم تنفيذ نمط الزائر عادة عن طريق التحميل الزائد. متخصصة قوالب وظيفة ليست حقا فكرة جيدة على أي حال.

ما فعلته ليس تسلسل القالب، ولكن وظيفة التحميل الزائد. إنه آمن.

ملاحظة: من الصعب القول ما إذا كان صحيحا أم لا، دون معرفة ما تحاول تحقيقه. ضع في اعتبارك أنه بغض النظر عن قالب تكنولوجيا المعلومات أو وظيفة مثقلة، سيتم اختيار المشغل في وقت الترجمة. إذا كنت بحاجة إلى Run-Time Dispatch، فأنت بحاجة إلى تعدد الأشكال، وليس التحميل الزائد. حسنا، ربما تعرف أنه على أي حال؛ فقط في حالة.

لديك

  • void operator()(bool b) هذه وظيفة غير templated
  • template< typename T > void operator()(T t) وهو قالب قاعدة منفصل يزيد الحمل أعلاه

هل يمكن أن يكون لديك تخصص كامل للثاني كما في template<> void operator(int i) التي لن تعتبر فقط متى void operator()(bool b) لم تتطابق.

يتم استخدام تخصص القالب الأساسي لتحديد أي من أساليب القالب الأساسية للاتصال. ومع ذلك، في حالتك، يكون لديك طريقة غير قالب ستحصل على أول.

المقالة لماذا لا تتخصص قوالب الوظائف؟ يعطي شرح جيد جدا لكيفية تحديد الطريقة.

في سوماري:

  1. تعتبر وظائف عدم القالب أولا (هذا هو المشغل العادي () (BOOL) أعلاه)
  2. يتم التحقق من قوالب قاعدة الوظائف الثانية (هذه هي دالة القبوبة الخاصة بك)، يتم تحديد قالب الأساس الأكثر تخصصا ثم إذا كان لديه تخصصا للأنواع الدقيقة التي يستخدمها التخصص على خلاف ذلك يتم استخدام القالب الأساسي مع الأنواع "الصحيحة" (انظر شرح في المقال)

مثال:

#include <iostream>
using namespace std;

struct doh
{
    void operator()(bool b)
    {
        cout << "operator()(bool b)" << endl;
    }

    template< typename T > void operator()(T t)
    {
        cout << "template <typename T> void operator()(T t)" << endl;
    }
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()<>(int i)
{
    cout << "template <> void operator()<>(int i)" << endl;
}
template<> void doh::operator()<>(bool b)
{
    cout << "template <> void operator()<>(bool b)" << endl;
}

int main()
{
    doh d;
    int i;
    bool b;
    d(b);
    d(i);
}

تحصل على مكالمات إلى:

operator()(bool b)       <-- first non template method that matches
template <> void operator()(int i)     <-- the most specialized specialization of templated function is called
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top