Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Определение члена-константы внутри/снаружи класса


Автор: zim22 11.8.2009, 16:38
Внутри класса не получается инициализировать константу значением функции.
Код

#include <cstdlib>

int fcn() { return rand(); }

struct Foo {
  static const int c = fcn(); // error C2057: expected constant expression
};


Если же вынести определение константы вне класса - то проблем нет.
Код

struct Foo {
  static const int c;
};
const int Foo::c = fcn(); 


Получается, что определение констант внутри класса является всего-лишь более ограниченной формой определения вне класса?
Код

struct Foo {
  static const int c = 5;
};

(т.е. внутри класса я должен константное выражение передать, а при инициализации вне класса - что угодно).

Автор: azesmcar 11.8.2009, 16:42
zim22

А вопрос в чем?

Автор: zim22 11.8.2009, 16:47
Цитата(azesmcar @  11.8.2009,  16:42 Найти цитируемый пост)
А вопрос в чем?

Цитата(zim22 @  11.8.2009,  16:38 Найти цитируемый пост)
Получается, что определение констант внутри класса является всего-лишь более ограниченной формой определения вне класса?

уточню вопрос:
допустим у нас есть такой код:
Код

struct Foo {
  static const int c;
  int arr[c]; //  error C2057: expected constant expression
};

const int Foo::c = fcn();

Почему ошибка? ведь с - константа.

Автор: azesmcar 11.8.2009, 16:52
Цитата

If a static data member is of const integral or const enumeration type, its declaration in the class
definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that
case, the member can appear in integral constant expressions. 
The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition shall not contain an initializer.


Цитата(zim22 @  11.8.2009,  16:47 Найти цитируемый пост)
Почему ошибка? ведь с - константа. 

Тут ошибка потому, что
Цитата

In that case, the member can appear in integral constant expressions

это не тот случай.

Автор: zim22 11.8.2009, 17:00
Цитата(azesmcar @  11.8.2009,  16:52 Найти цитируемый пост)
and the namespace scope definition shall not contain an initializer

я нарушил стандарт, да?
***
нет. я его не нарушил.
всё это:
Цитата

If a static data member is of const integral or const enumeration type, its declaration in the class
definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that
case, the member can appear in integral constant expressions. The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition shall not contain an initializer.

относилось к такому случаю:
Код

struct Foo {
  static const int c = 7;
  int arr[c];
};
const int Foo::c;

Автор: azesmcar 11.8.2009, 17:04
Цитата(zim22 @  11.8.2009,  17:00 Найти цитируемый пост)
я нарушил стандарт, да? 

Ну, раз не компилируется smile 
Если инициализировать "на месте", это компайл-тайм константа, ею можно специализировать шаблоны, создавать массивы, а как вы предполагаете инициализировать константу рантайм и использовать ее в compile-time (создавать массив)?

Добавлено через 1 минуту и 54 секунды
Цитата(zim22 @  11.8.2009,  17:00 Найти цитируемый пост)
всё это:
относилось к такому случаю:

Да, и там описано что только в этом случае

Цитата(azesmcar @  11.8.2009,  16:52 Найти цитируемый пост)
In that
case, the member can appear in integral constant expressions. 


Автор: zim22 11.8.2009, 17:07
Цитата(azesmcar @  11.8.2009,  17:04 Найти цитируемый пост)
а как вы предполагаете инициализировать константу рантайм и использовать ее в compile-time?

инициализировать константу рантайм получилось:
Код

#include <cstdlib>

int fcn() { return rand(); }
struct Foo {
  static const int c;
};
const int Foo::c = fcn(); 

а вот в компайл тайм использовать не получится... smile

Автор: azesmcar 11.8.2009, 17:09
Цитата(zim22 @  11.8.2009,  17:07 Найти цитируемый пост)
инициализировать константу рантайм получилось:

инициализировать можно, но...тут ведь дело не в инициализации а в использовании
Код

int fcn()
{
    return 10;
}


int main()
{
    const int i = fcn();
    int c[i];
}

вот это ведь не будет работать? Что нужно чтобы это заработало?
Код

int fcn()
{
    return 10;
}


int main()
{
    const int i = 10;
    int c[i];
}

теперь i - константа времени компиляции, все работает.
Откуда во время компиляции, компилятор узнает о значении, которое будет ясно лишь на этапе выполнения. Т.е. как вы предполагаете использовать эту константу?

zim22 кажется понял. Вы забываете про то, что в C++ два вида констант
Константа времени выполнения и константа времени компиляции.

Добавлено
не так понял smile
Цитата(zim22 @  11.8.2009,  17:07 Найти цитируемый пост)
а вот в компайл тайм использовать не получится... smile 

прочитал как не получАется smile но все равно, оставлю пост.

Автор: zim22 11.8.2009, 17:16
Цитата(azesmcar @  11.8.2009,  17:09 Найти цитируемый пост)
 Т.е. как вы предполагаете использовать эту константу?

я ещё не придумал smile
но преимущества есть. это ведь Константа! и изменять её значение мы не можем, после того, как она будет инициализирована.

Например такой код позволит нам самим устанавливать значение константы! а не зашивать её в программу.
Код

int fcn() { 
  int res; 
  std::cin >> res; 
  return res; 
}
struct Foo {
  static const int c;
};
const int Foo::c = fcn(); 

Автор: azesmcar 11.8.2009, 17:18
Цитата(zim22 @  11.8.2009,  17:16 Найти цитируемый пост)
я ещё не придумал smile
но преимущества есть. это ведь Константа! и изменять её значение мы не можем, после того, как она будет инициализирована.

Я имел ввиду на этапе компиляции, а так, думаю применение найдется smile

Автор: mes 11.8.2009, 17:40
Вам поможет constexpr из грядущего стандарта, которая позволит явно разделить константы на два лагеря : readonly и constexpr.
http://en.wikipedia.org/wiki/C%2B%2B0x#Generalized_constant_expressions

Автор: zim22 11.8.2009, 17:46
Цитата(mes @  11.8.2009,  17:40 Найти цитируемый пост)
Вам поможет constexpr из грядущего стандарта

супер!  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)