Здравствуйте, igna, Вы писали:
I>Как вы объявляете константы внутри класса, как enum или как static const? Или в зависимости от обстоятельств? Каких?
Когла как
Если код какой-то совсем новый и перпендикулярный старому, что static const, а если в рамках старого, то enum, из соображений единообразия.
В принципе, static const даёт только то преимущество, что можно задать тип константы, но так как у нас "продвинутые" шаблоны не используются, то обычно тип констнанты не особо важен.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, igna, Вы писали:
I>Как вы объявляете константы внутри класса, как enum или как static const? Или в зависимости от обстоятельств? Каких?
Если независимая костанта, то static const,
если набор связанных констант (типа номеров столбцов) или маски, то enum
Здравствуйте, Roman Odaisky, Вы писали:
RO>BOOST_STATIC_CONSTANT
Спасибо, а из какой это библиотеки? Или как на www.boost.org найти что-нибудь по имени? Search Boost выдает вот что. Ну или вот, если искать только в документации.
Re: Константы в объявлении класса
От:
Аноним
Дата:
28.08.07 10:05
Оценка:
static const , если много — то групирую во вложенные namespace и пишу в отдельных файлах, подключая include-ом. Очень удобно, когда все константы в одном окне, к тому же позволяет быстро оторваться от константности.
Здравствуйте, igna, Вы писали:
I>Как вы объявляете константы внутри класса, как enum или как static const? Или в зависимости от обстоятельств? Каких?
Обычно использую enum, если целого типа достаточно, т.к. static cont int почему-то медленнее enum, особенно под vs80 здесь
Здравствуйте, igna, Вы писали:
RO>>BOOST_STATIC_CONSTANT ;-)
I>Спасибо, а из какой это библиотеки? Или как на www.boost.org найти что-нибудь по имени? Search Boost выдает
Спасибо за ответы. Сам, как и большинство, использую static const, но вот что прочитал у David Vandevoorde, Nicolai M. Josuttis в C++ Templates: The Complete Guide:
17.2 Enumeration Values versus Static Constants
In old C++ compilers, enumeration values were the only available possibility to have "true constants" (so-called constant-expressions) inside class declarations. However, this has changed during the standardization of C++, which introduced the concept of in-class static constant initializers. A brief example illustrates the construct:
struct TrueConstants {
enum { Three = 3 };
static int const Four = 4;
};
In this example, Four is a "true constant"—just as is Three.
With this, our Pow3 metaprogram may also look as follows:
// meta/pow3b.hpp #ifndef POW3_HPP
#define POW3_HPP
// primary template to compute 3 to the Nth template<int N>
class Pow3 {
public:
static int const result = 3 * Pow3<N-1>::result;
};
// full specialization to end the recursion template<>
class Pow3<0> {
public:
static int const result = 1;
};
#endif// POW3_HPP
The only difference is the use of static constant members instead of enumeration values. However, there is a drawback with this version: Static constant members are lvalues. So, if you have a declaration such as
void foo(int const&);
and you pass it the result of a metaprogram
foo(Pow3<7>::result);
a compiler must pass the address of Pow3<7>::result, which forces the compiler to instantiate and allocate the definition for the static member. As a result, the computation is no longer limited to a pure "compile-time" effect.
Enumeration values aren't lvalues (that is, they don't have an address). So, when you pass them "by reference," no static memory is used. It's almost exactly as if you passed the computed value as a literal. These considerations motivate us to use enumeration values in all metaprograms throughout this book.
Согласны ли вы с тем, что при написании метапрограмм лучше использовать enum, а не static const?
I>a compiler must pass the address of Pow3<7>::result, which forces the compiler to instantiate and allocate the definition for the static member. As a result, the computation is no longer limited to a pure "compile-time" effect.
А вот это интересно, может кто-нибудь прокомментировать?
I>Согласны ли вы с тем, что при написании метапрограмм лучше использовать enum, а не static const?
Ну вообще, со второго взгляда, всё не так уж и плохо, т.к. член-то всё-таки статический, т.е. его экземпляр будет создан один на класс. Один int на класс — не такая уж и большая цена.
Он не упомянул типизацию констант.
Мне часто приходится объявлять unsigned константы, и хотелось бы, что бы они были именно unsigned.
Или bool — true и false выразительнее 0 и 1, и варнингов нет.
Здравствуйте, igna, Вы писали: RO>>BOOST_STATIC_CONSTANT
I>Спасибо, а из какой это библиотеки? Или как на www.boost.org найти что-нибудь по имени? Search Boost выдает вот что. Ну или вот, если искать только в документации.
Тогда, конечно, я всегда использую static const для compile-time констант. Что ж ещё?
Если же вопрос касался констант обоих типов, поясню, чем мне так нравится enum.
Enum — это всё-таки user defined type. Конечно, вряд ли кто-нибудь будет переопределять operator ++ для своего enum'a, но всё-таки тот факт, что группа значений имеет свой тип даёт ряд преимуществ:
нельзя подставить Temperature::WARM вместо Solidity::SOFT (без преобразования);
нельзя подставить int вместо элемента перечисления (без преобразования);
можно typedef'ить;
можно не заморачиваться присваиванием значений каджому элементу, если это не нужно (мне, например, может быть фиолетово, что Solidity::SOFT == 22).
Да, нельзя сделать элементы перечисления double'ом или std::string'ом.
В проекте, в котором я сейчас работаю, static const применяется намного реже enum. Сложно сейчас сказать, почему это происходит. Наверное, потому, что нам часто нужно именно перечисление и намного реже — константы. В этом случае мы, конечно же, используем static const даже для констант интегральных типов (в качестве примера см. HANDLES_MAX выше).
Поэтому мне непонятно, зачем всегда использовать int const вместо enum. Для унификации? Для подражания ранним версиям явы?
Здравствуйте, remark, Вы писали:
I>>a compiler must pass the address of Pow3<7>::result, which forces the compiler to instantiate and allocate the definition for the static member. As a result, the computation is no longer limited to a pure "compile-time" effect.
R>А вот это интересно, может кто-нибудь прокомментировать?
Компилятор обязан не ругаясь размещать константы, если хоть где-то у них берётся адрес. AFAIR, ему запрещено размещать их, если адрес не берётся, но тут не уверен.
A строка вида &EnumElement всегда приведёт к ошибке компиляции.
Ты, наверное, не обратил внимания на то, что foo() принимает ссылку:
void foo( int const& );
Таким образом, когда ты пишешь
foo( Pow3<7>::result );
Компилятор НЕ воспринимает это как
foo( int( Pow3<7>::result ) );
И честно пытается передать ссылку, пускай и константную — а вдруг ты там внутри const_cast сделаешь?
Для того, чтобы сделать ссылку, компилятору нужно взять адрес. Для того, чтобы у константы был адрес, компилятору нужно эту константу где-то разместить. Таким образом, константа будет жить не только во время компиляции и "pure compile-time effect" пропадает.
I>Согласны ли вы с тем, что при написании метапрограмм лучше использовать enum, а не static const? R>Один int на класс — не такая уж и большая цена.
Согласен. По крайней мере, на этих примерах разница несущественная.
Здравствуйте, drx, Вы писали:
drx>A строка вида &EnumElement всегда приведёт к ошибке компиляции.
Не приведет. Вот, попробуй:
void foo( int const& );
enum { some_const = 123 };
int main()
{
foo( some_const );
}
#Если удалось откомпилировать,
# читай дальше,
#иначе
# используй Comeau.
drx>И честно пытается передать ссылку, пускай и константную — а вдруг ты там внутри const_cast сделаешь? drx>Для того, чтобы сделать ссылку, компилятору нужно взять адрес. Для того, чтобы у константы был адрес, компилятору нужно эту константу где-то разместить. Таким образом, константа будет жить не только во время компиляции и "pure compile-time effect" пропадает.
Разве нельзя точно также порассуждать по поводу enum?
Здравствуйте, remark, Вы писали:
R>Ну вообще, со второго взгляда, всё не так уж и плохо, т.к. член-то всё-таки статический, т.е. его экземпляр будет создан один на класс. Один int на класс — не такая уж и большая цена.
Согласен. Кстати, компилятору запрещено соптимизировать этот int, если он используется только как аргумент встраиваемой функции?