كيف يمكنني كتابة قالب وظيفة لجميع الأنواع ذات سمة نوع معينة؟

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

  •  22-09-2019
  •  | 
  •  

سؤال

النظر في المثال التالي:

struct Scanner
{
    template <typename T>
    T get();
};

template <>
string Scanner::get()
{
    return string("string");
}

template <>
int Scanner::get()
{
    return 10;
}

int main()
{
    Scanner scanner;
    string s = scanner.get<string>();
    int i = scanner.get<int>();
}

ال Scanner يستخدم الفصل لاستخراج الرموز من بعض المصادر. الرمز أعلاه يعمل بشكل جيد ، لكنه يفشل عندما أحاول ذلك get أنواع لا يتجزأ الأخرى مثل أ char أو unsigned int. الرمز لقراءة هذه الأنواع هو بالضبط نفس الرمز لقراءة int. يمكنني فقط تكرار الكود لجميع الأنواع المتكاملة الأخرى التي أرغب في قراءتها ، لكنني أفضل تحديد قالب وظيفة واحدة لجميع الأنواع المتكاملة.

لقد جربت ما يلي:

struct Scanner
{
    template <typename T>
    typename enable_if<boost::is_integral<T>, T>::type get();
};

الذي يعمل مثل السحر ، لكنني غير متأكد من كيفية الحصول عليه Scanner::get<string>() للعمل مرة أخرى. لذا ، كيف يمكنني كتابة الرمز حتى أتمكن من القيام به scanner.get<string>() و scanner.get<any integral type>() ولديك تعريف واحد لقراءة جميع الأنواع المتكاملة؟

تحديث: سؤال المكافأة: ماذا لو كنت أرغب في قبول أكثر من مجموعة من الفصول على أساس بعض السمات؟ على سبيل المثال: كيف يجب أن أتعامل مع هذه المشكلة إذا كنت أرغب في الحصول على ثلاثة get الوظائف التي تقبل (1) الأنواع المتكاملة (2) أنواع النقاط العائمة (3) ، على التوالي.

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

المحلول

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }
    template <typename T>
    typename boost::disable_if<boost::is_integral<T>, std::string>::type get()
    {
        return "string";
    }
};

تحديث "ماذا لو كنت أرغب في قبول أكثر من مجموعة من الفصول على أساس بعض السمات؟"

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }

    template <typename T>
    typename boost::enable_if<boost::is_floating_point<T>, T>::type get()
    {
        return 11.5;
    }

    template <typename T>
    std::string get(
          typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
          typename boost::disable_if<boost::is_integral<T>, T>::type* = 0)

    {
        return std::string("string");
    }
};

نصائح أخرى

تأجيل قالب آخر. هذا هو النمط العام لما تريده:

template <typename T, bool HasTrait = false>
struct scanner_impl;

template <typename T>
struct scanner_impl
{
    // Implement as though the trait is false
};

template <typename T>
struct scanner_impl<true>
{
    // Implement as though the trait is true
};

// This is the one the user uses
template <typename T>
struct scanner : scanner_impl<T, typename has_my_trait<T>::value>
{
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top