كيفية تخصص وظائف الأعضاء بناءً على حجة قالب الفصل
-
30-09-2019 - |
سؤال
ماذا يقول السؤال. بالإضافة إلى ذلك ، هل من الممكن القيام بذلك مضمّنًا؟
إليك مثال صغير فقط لإعطاء فكرة ...
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void do( const Foo<T> &f ) {
z = f.z;
}
// specialize 'do' for Foo<int>, possible inline?
private:
T z;
};
المحلول
يمكنك الحصول على هذا السلوك من خلال جعل وظيفة العضو قالب وظيفة العضو واستخدام SFINAE (فشل الاستبدال ليس خطأ). فمثلا:
template <typename U>
typename std::enable_if<!std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
template <typename U>
typename std::enable_if<std::is_integral<U>::value &&
std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}
ال is_integral
اكتب اختبار السمات سواء U
هو نوع عدد صحيح. إذا لم يكن كذلك ، يتم إنشاء الأول ؛ إذا كان ذلك ، يتم إنشاء مثيل للثاني.
ال is_same
اكتب اختبارات السمات للتأكد T
و U
هي نفس النوع. يتم استخدام هذا لضمان عدم إنشاء قالب وظيفة العضو لأي نوع غيره Foo<T>
.
هذا المثال يستخدم C ++ 0x <type_traits>
مكتبة؛ تعزيز أيضا مكتبة سمات النوع التي يمكنك استخدامها ، والتي تعمل في الغالب.
نصائح أخرى
لا تحتاج إلى فعل أي شيء معقد. فقط استخدم التحميل الزائد والتفويض. لاحظ أنه لا يمكننا فقط إضافة ملف int
الحمل الزائد ، لأنه متى T
تبين أن int
أيضًا ، سيكون هذا تحميلًا زائد غير صالح (وظيفتان بنفس التوقيع)
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
doItImpl(f);
}
private:
template<typename U>
void doItImpl(const Foo<U> &f) {
z = f.z;
}
void doItImpl(const Foo<int> &f) {
/* ... */
}
private:
T z;
};
أو ، في هذه الحالة ، يمكنك القيام بذلك عن طريق التخصص
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
void doIt(const Foo<T> &f ) {
z = f.z;
}
private:
T z;
};
template<>
inline void Foo<int>::doIt(const Foo<int> &f) {
/* ... */
}
لا يمكن استخدام التخصص بهذه الطريقة إلا إذا تم إصلاح جميع وسيطات القالب. وبعبارة أخرى ، فإن وظيفة العضو غير ممكنة جزئيًا.
قد تحاول أن تفعل شيئًا كهذا (لم يختبر ، قد لا يعمل):
template<typename T>
class Foo {
public:
Foo() :z(0.0) {}
template<typename Ty = T>
void do( const Foo<T> &f ) {
z = f.z;
}
template<>
void do<int>( const Foo<T> &f ) {
//specialized code
}
private:
T z;
};