[c++] كيف يمكنني التكرار على التعداد؟


Answers

واحدة من العديد من الطرق: عندما enum فقط لا يكفي: فئات التعداد ل C ++ .

وإذا كنت تريد شيئًا أكثر تجانسًا ، فجرّب هذا المنهج من James Kanze.

Question

لقد لاحظت فقط أنه لا يمكنك استخدام معاملات الرياضيات القياسية على التعداد مثل ++ أو + =

فما هي أفضل طريقة للتكرار من خلال جميع القيم في التعداد C ++؟




#include <iostream>
#include <algorithm>

namespace MyEnum
{
  enum Type
  {
    a = 100,
    b = 220,
    c = -1
  };

  static const Type All[] = { a, b, c };
}

void fun( const MyEnum::Type e )
{
  std::cout << e << std::endl;
}

int main()
{
  // all
  for ( const auto e : MyEnum::All )
    fun( e );

  // some
  for ( const auto e : { MyEnum::a, MyEnum::b } )
    fun( e );

  // all
  std::for_each( std::begin( MyEnum::All ), std::end( MyEnum::All ), fun );

  return 0;
}



لمترجم MS:

#define inc_enum(i) ((decltype(i)) ((int)i + 1))

enum enumtype { one, two, three, count};
for(enumtype i = one; i < count; i = inc_enum(i))
{ 
    dostuff(i); 
}

ملاحظة: يعد هذا رمزًا أقل كثيرًا من الإجابة البسيطة المُجمَّعة المخصصة المُعدة.

يمكنك الحصول على هذا للعمل مع دول مجلس التعاون الخليجي باستخدام typeof بدلا من decltype ، ولكن ليس لدي هذا المجمع سهل في الوقت الراهن للتأكد من أنه يجمع.




يمكنك محاولة تعريف الماكرو التالي:

#define for_range(_type, _param, _A1, _B1) for (bool _ok = true; _ok;)\
for (_type _start = _A1, _finish = _B1; _ok;)\
    for (int _step = 2*(((int)_finish)>(int)_start)-1;_ok;)\
         for (_type _param = _start; _ok ; \
 (_param != _finish ? \
           _param = static_cast<_type>(((int)_param)+_step) : _ok = false))

الآن يمكنك استخدامه:

enum Count { zero, one, two, three }; 

    for_range (Count, c, zero, three)
    {
        cout << "forward: " << c << endl;
    }

يمكن استخدامه للتكرار إلى الوراء وإلى الأمام من خلال غير الموقعة ، والأعداد الصحيحة ، والتعدادات والتشكيلات:

for_range (unsigned, i, 10,0)
{
    cout << "backwards i: " << i << endl;
}


for_range (char, c, 'z','a')
{
    cout << c << endl;
}

على الرغم من تعريفه المحرج فإنه يتم تحسينه بشكل جيد للغاية. نظرت في المجمع في VC ++. الشفرة فعالة للغاية. لا يمكن تأجيلها ، ولكن الثلاثة للإفادات: سينتج المترجم حلقة واحدة فقط بعد التحسين! يمكنك حتى تحديد الحلقات المغلقة:

unsigned p[4][5];

for_range (Count, i, zero,three)
    for_range(unsigned int, j, 4, 0)
    {   
        p[i][j] = static_cast<unsigned>(i)+j;
    }

من الواضح أنك لا تستطيع التكرار من خلال الأنواع المعدودة ذات الثغرات.




يمكنك أيضا زيادة التحميل على مشغلي الزيادة / التناقص لنوع تعداد الخاص بك.




معقدة للغاية هذه الحلول ، وأنا أحب ذلك:

enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};

const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };

for (NodePosition pos : NodePositionVector) {
...
}



إذا كنت تعلم أن قيم التعداد كانت متسلسلة ، على سبيل المثال ، Qt: Key enum ، فيمكنك:

Qt::Key shortcut_key = Qt::Key_0;
for (int idx = 0; etc...) {
    ....
    if (shortcut_key <= Qt::Key_9) {
        fileMenu->addAction("abc", this, SLOT(onNewTab()),
                            QKeySequence(Qt::CTRL + shortcut_key));
        shortcut_key = (Qt::Key) (shortcut_key + 1);
    }
}

يعمل كما هو متوقع.




يقول أحد الإجابات: "إذا كنت تعلم أن قيم التعداد كانت متسلسلة ، على سبيل المثال ، Qt: Key enum".

Qt :: Key القيم غير متسلسلة . بعض الشرائح في التعداد هي.

مؤشر الترابط هذا حول iterating على كافة القيم في التعداد. هذا ممكن فعلاً في Qt بسبب استخدامه لنظام Meta Object System:

const QMetaObject *metaObject = qt_getQtMetaObject();
QMetaEnum keyEnum = metaObject->enumerator(metaObject->indexOfEnumerator("Key"));
for (int i = 0; i < keyEnum.keyCount(); ++i) {
    qDebug() << keyEnum.key(i);
}

راجع أيضًا QObject :: metaObject () و Q_ENUM الماكرو.

أعتقد أن هذا النوع من الأشياء سوف يصبح أسهل مع C ++ 20؟ لكني لم أنظر في ذلك.




Related



Tags

c++ c++   enums