هل هناك أي طريقة للإدلاء باستخدام مشغل الفصل فقط؟

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

سؤال

نوع من السؤال العشوائي..

ما أبحث عنه هو طريقة للتعبير عن عملية الإرسال التي تستخدم عامل تشغيل محددًا لمثيل الفئة الذي أقوم بالإرسال منه، ويولد خطأ في وقت الترجمة إذا لم يكن هناك عامل تشغيل محدد للنوع.لذا، على سبيل المثال، ما أبحث عنه هو شيء مثل:

template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
    return tValue.operator RESULT_TYPE();
}

// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );

// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );

ملاحظة جانبية مثيرة للاهتمام:يتعطل الكود أعلاه في برنامج التحويل البرمجي VS2005 C++، ولا يتم تجميعه بشكل صحيح في برنامج التحويل البرمجي VS2008 C++ بسبب ما أعتقد أنه خطأ في برنامج التحويل البرمجي، ولكن نأمل أن يوضح الفكرة.

هل يعرف أحد أي طريقة لتحقيق هذا التأثير؟

يحرر:مزيد من التبرير، لشرح سبب استخدامك لهذا.لنفترض أن لديك فئة مجمعة من المفترض أن تقوم بتغليف أو تجريد نوع ما، وأنك ترسله إلى النوع المغلف.يمكنك استخدام static_cast<>، ولكن قد ينجح ذلك عندما تريد أن يفشل (على سبيل المثال:يختار المترجم عاملاً يُسمح له بالتحويل إلى النوع الذي طلبته، عندما تريد الفشل لأن هذا العامل غير موجود).

من المسلم به أنها حالة غير شائعة، ولكن من المزعج أنني لا أستطيع التعبير بالضبط عما أريد أن يفعله المترجم في دالة مغلفة...ومن هنا السؤال هنا.

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

المحلول

الكود الذي نشرته يعمل مع مترجم كامو (وهذا عادة ما يكون مؤشرًا جيدًا على أنه صالح لـ C++).

كما تعلم، فإن طاقم الممثلين الصالح لا يتكون من أكثر من فريق عمل محدد من قبل مستخدم واحد، لذا فإن الحل المحتمل الذي كنت أفكر فيه هو إضافة فريق عمل آخر محدد من قبل مستخدم عن طريق تحديد نوع جديد في قالب فريق التمثيل والحصول على تأكيد ثابت أنه لا يتوفر أي طاقم من النوع الجديد إلى نوع النتيجة (باستخدام التعزيز قابل للتحويل)، إلا أن هذا لا يميز بين مشغلي الإرسال ومنشئي الإرسال (مقطع ذو وسيطة واحدة) ويسمح بإجراء عمليات تحويل إضافية (على سبيل المثال. void* ل bool).لست متأكدًا مما إذا كان التمييز بين مشغلي فريق التمثيل ومنشئي فريق التمثيل هو الحل صحيح الشيء الذي يجب القيام به ولكن هذا ما ينص عليه السؤال.

بعد بضعة أيام من التفكير في هذا الأمر، يمكنك ببساطة الحصول على عنوان مشغل فريق التمثيل.إن قول هذا أسهل قليلاً من فعله نظرًا لمؤشر C++ المشعر لبناء جملة العضو (لقد استغرق الأمر وقتًا أطول من المتوقع لأقوم بذلك بشكل صحيح).لا أعرف إذا كان هذا يعمل على VS2008، لقد تحققت منه فقط على Cameau.

template< typename Res, typename T>
Res operator_cast( const T& t )
{
    typedef Res (T::*cast_op_t)() const;
    cast_op_t cast_op = &T::operator Res;
    return (t.*cast_op)();
}

يحرر: لقد أتيحت لي الفرصة لاختباره على VS2005 وVS2008.النتائج التي توصلت إليها تختلف عن الملصق الأصلي.

  • في VS2008 يبدو أن الإصدار الأصلي يعمل بشكل جيد (كما هو الحال بالنسبة لي).
  • في VS2005، يتعطل الإصدار الأصلي للمترجم فقط عند الإرسال من نوع مدمج (على سبيل المثال.casting int to int) بعد تقديم خطأ في الترجمة والذي لا يبدو سيئًا جدًا بالنسبة لي ويبدو أن الإصدار الخاص بي يعمل في جميع الحالات.

نصائح أخرى

وباستخدام منشئ تحويل وضع علامة صريحة هو كيف لك من شأنه أن يمنع مترجم من السماح أنواع المحولة ضمنا من تهيئة فئة المجمع الخاص بك.

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

#include <string>

// Class to trigger compiler warning   
class NO_OPERATOR_CONVERSION_AVAILABLE
{
private:
   NO_OPERATOR_CONVERSION_AVAILABLE(){};
};

// Default template definition to cause compiler error
template<typename T1, typename T2> T1 operator_cast(const T2&)
{
   NO_OPERATOR_CONVERSION_AVAILABLE a;
   return T1();
}

// Template specialisation
template<> std::string operator_cast(const std::string &x)
{
   return x;
}

ويبدو وكأنه كنت تريد قالب التخصص، فإن شيئا من هذا القبيل القيام به:

/* general template */
template<typename T1, typename T2> T1 operator_cast(const T2 &x);

/* do this for each valid cast */
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }

وتحرير: وكما لوحظ في وظيفة أخرى، يمكنك وضع شيء في النسخة العام لتعطيك رسالة خطأ أكثر فائدة إذا تم تنفيذ يلقي غير معتمد

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top