Как перечисления битовых флагов C должны быть переведены в C ++? - PullRequest
3 голосов
/ 14 октября 2008

C ++ - это в основном надмножество C, но не всегда. В частности, хотя значения перечисления в C и C ++ неявно преобразуются в int, обратное неверно: только в C целые числа преобразуют обратно в значения перечисления. Таким образом, битовые флаги, определенные с помощью объявлений перечисления, работают неправильно. Следовательно, это нормально в C, но не в C ++:

typedef enum Foo
{
    Foo_First = 1<<0,
    Foo_Second = 1<<1,
} Foo;

int main(void)
{
    Foo x = Foo_First | Foo_Second; // error in C++
    return 0;
}

Как решить эту проблему эффективно и правильно, в идеале, без ущерба для дружественного к отладчику характера использования Foo в качестве типа переменной (он разлагается на битовые флаги компонента в часах и т.

Учтите также, что могут быть сотни таких перечислений флагов и многие тысячи точек использования. В идеале какая-то эффективная перегрузка оператора могла бы сделать свое дело, но это действительно должно быть эффективным; приложение, которое я имею в виду, предназначено для вычислений и имеет репутацию быстрого.

Пояснение: я перевожу большую (> 300 КБ) программу на C на C ++, поэтому я ищу эффективный перевод как во время выполнения, так и во время разработки. Простая вставка приведений во все подходящие места может занять несколько недель.

Ответы [ 3 ]

8 голосов
/ 14 октября 2008

Почему бы просто не привести результат обратно к Foo?

Foo x = Foo(Foo_First | Foo_Second);

РЕДАКТИРОВАТЬ: Я не понял масштаб вашей проблемы, когда я впервые ответил на этот вопрос. Выше будет работать для нескольких точечных исправлений. Для того, что вы хотите сделать, вам нужно определить | оператор, который принимает 2 аргумента Foo и возвращает Foo:

Foo operator|(Foo a, Foo b)
{
    return Foo(int(a) | int(b));
}

Цели int используются для предотвращения нежелательной рекурсии.

2 голосов
/ 14 октября 2008

Это звучит как идеальное приложение для приведения - вы должны сказать компилятору, что да, вы действительно хотите создать Foo со случайным целым числом.

Конечно, технически говоря, Foo_First | Foo_Second не является допустимым значением для Foo.

0 голосов
/ 14 октября 2008

Либо оставьте результат как int или static_cast:

Foo x = static_cast<Foo>(Foo_First | Foo_Second); // not an error in C++
...