Все ли компиляторы C ++ позволяют использовать статическую переменную-член класса const int в качестве границы массива? - PullRequest
8 голосов
/ 25 августа 2009

В VC ++, когда мне нужно указать массив для переменной члена класса, я делаю это так:

 class Class {

 private:
     static const int numberOfColors = 16;
     COLORREF colors[numberOfColors];
 };

(пожалуйста, не говорите мне об использовании std :: vector здесь)

Таким образом, у меня есть константа, которую можно использовать в качестве привязки к массиву, а затем в коде класса, чтобы указать ограничения оператора цикла, и в то же время ее больше нигде не видно.

Вопрос в том, разрешено ли это использование static const int переменных-членов только для VC ++ или обычно разрешено другими распространенными компиляторами?

Ответы [ 9 ]

13 голосов
/ 25 августа 2009

Такое поведение допустимо в соответствии со стандартом C ++. Любой недавний компилятор должен поддерживать его.

13 голосов
/ 25 августа 2009

Это допустимый C ++, и большинство (все?) Достаточно современных компиляторов поддерживают его. Если вы используете boost, вы можете получить портативную поддержку для этой функции в виде BOOST_STATIC_CONSTANT macro:

class Class {
 private:
     BOOST_STATIC_CONSTANT(int, numberOfColors = 16);
     COLORREF colors[numberOfColors];
 };

Макрос расширяется до static const int numberOfColors = 16, если компилятор поддерживает это, в противном случае он прибегает к enum { numberOfColors=16 };.

6 голосов
/ 25 августа 2009

Я считаю, что Visual Studio 2005 и более поздние версии поддерживают его. Компилятор XCode C ++ также (на самом деле это gcc).

Если вы хотите быть в безопасности, вы всегда можете использовать старый взлом enum, который я узнал из Effective C ++. Это выглядит так:

class Class {

 private:
     enum {
        numberOfColors = 16
     };
     COLORREF colors[numberOfColors];
 };

Надеюсь, это поможет.

6 голосов
/ 25 августа 2009

Это стандарт C ++ уже более десяти лет. Это даже поддерживается VC - что еще можно хотеть? (@Neil: А как насчет SunCC? :^>)

4 голосов
/ 25 августа 2009

Да, это на 100% законно и должно быть портативным. Стандарт C ++ говорит об этом в 5.19 - «Постоянные выражения» (выделено мной):

В некоторых местах C ++ требует выражения, которые оцениваются как интеграл или константа перечисления: как границы массива (8.3.4, 5.3.4), как выражения случая (6.4.2), как длины битового поля (9.6) , как инициализаторы перечислителя (7.2), как инициализаторы статического члена (9.4.2), так и как аргументы шаблонного типа или нетипичного перечисления (14.3).

constant-expression:
    conditional-expression

Интегральное константное выражение может включать только литералы (2.13), перечислители, константные переменные или члены-статические данные целочисленных типов или типов перечислений, инициализированных константными выражениями (8.5), нетипизированные параметры шаблона интеграла или типы перечисления и размер выражений.

Тем не менее, похоже, что VC6 не поддерживает его. См. StackedCrooked ответ для хорошего обходного пути. На самом деле, я обычно предпочитаю enum метод StackedCrooked, упоминаемый для этого типа вещей.

Как к сведению, метод "static const" работает в VC9, GCC 3.4.5 (MinGW), Comeau и Digital Mars.

И не забывайте, что если вы используете член "static const", вам потребуется определение для него в дополнение к объявлению , строго говоря. Однако практически все компиляторы позволят вам пропустить определение в этом случае.

3 голосов
/ 25 августа 2009

Помимо других ответов вы можете использовать следующую функцию для определения количества элементов в статически размещенных массивах:

template<typename T, size_t length>
size_t arrayLength(T (&a)[length])
{
    return length;
}
2 голосов
/ 25 августа 2009

Я почти уверен, что это также будет работать с gcc и Solaris, но сейчас я не могу это проверить.

В будущем вы можете расширить идею, как это:

template<int size>
class Class {
private:
    COLORREF colors[size];
};

и используйте его так:

Class<5> c;

, чтобы вы не ограничивались одним размером буфера в вашем приложении.

1 голос
/ 25 августа 2009

Я перестал беспокоиться о переносимости этого года назад. Возможно, еще есть компиляторы, которые не поддерживают его, но я недавно не встречал ни одного из них.

0 голосов
/ 25 августа 2009

На такие вопросы можно ответить, сославшись на спецификацию ISO C ++, но людям сложно получить эту спецификацию и ее труднее читать. Я думаю, что самый простой ответ зависит от двух вещей:

  • Microsoft Visual Studio 2005 и выше является относительно совместимой реализацией C ++. Если это позволяет вам что-то делать, шансы являются его стандартом.
  • Загрузите что-то вроде Code :: Blocks, чтобы получить компилятор GCC, чтобы попробовать что-то. Если он работает в MS и GCC, шансы действительно есть, его стандарт.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...