يثير مجموعة enable_if + disable_if مكالمة غامضة
سؤال
أثناء محاولة الإجابة هذا السؤال أردت أن أقترح استخدام enable_if
+ disable_if
للسماح بالحمل الزائد للطريقة بناءً على حقيقة أن النوع كان (أو لا) متعدد الأشكال.
لذلك قمت بإنشاء ملف اختبار صغير:
template <class T>
void* address_of(T* p,
boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}
الذي يبدو ترويضا تماما.
ومع ذلك GCC (3.4 ...) خنق على هذا:
test.cpp: في الوظيفة
int main(int, char**)
:
test.cpp: 29: خطأ: Call of Overloadingaddress_of(N*)
غامض
Test.CPP: 17: ملاحظة: المرشحون هم:void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*)
مع t = n
test.cpp: 20: ملاحظة:void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)
مع t = n
يبدو من الواضح إلى حد ما لعقلي البشري الذي يجب استخدام الحمل الزائد هنا. أعني أنه يبدو من الواضح أنني قد حددت بديلاً ويمكن استخدام وظيفة واحدة فقط في وقت واحد ... وكنت أعتقد أن Sfinae ستهتم بإبطال الحمل الزائد غير الضروري.
لقد قمت بتصحيحه باستخدام ...
(القطع النخاعية) بدلا من disable_if
ويتطلب حجة ثانية وهمية ... لكنني ما زلت مهتمًا بالسبب في اختنق المترجم في هذا الأمر.
المحلول
اختنق المترجم لأنك نسيت الفائدة ::type
على enable_if
و disable_if
. يتم تعريف القوالب دائمًا ؛ إنه مجرد العضو type
موجود إذا وفقط إذا كان التعبير true
(إلى عن على enable_if
) أو false
(إلى عن على disable_if
).
template <class T>
void* address_of(T* p,
أكتب اسم boost::enable_if< boost::is_polymorphic<T> >::يكتب* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
أكتب اسم boost::disable_if< boost::is_polymorphic<T> >::يكتب* dummy = 0)
{ return static_cast<void*>(p); }
بدون زائدة ::type
, ، قوالب وظيفتك فقط تنشئ أحمالًا زائدة تأخذ مؤشرات إلى مثيلات من enable_if
أو disable_if
كمعلمة ثانية. مع الزائدة ::type
, ، إما أن تقوم القوالب بإنشاء تحميل زائد مع معلمة ثانية من النوع void*
, أو تتم إزالة الحمل الزائد (أي السلوك المطلوب).
نصائح أخرى
باستخدام إصدار "نوع الإرجاع" من enable_if يعمل في 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>
template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }
template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}