كيف يمكنني كتابة قالب وظيفة لجميع الأنواع ذات سمة نوع معينة؟
-
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>
{
};