В PHP и C # константы могут быть инициализированы по мере их объявления:
class Calendar3
{
const int value1 = 12;
const double value2 = 0.001;
}
У меня есть следующее объявление C ++ функтора, которое используется с другим классом для сравнения двух математических векторов:
struct equal_vec
{
bool operator() (const Vector3D& a, const Vector3D& b) const
{
Vector3D dist = b - a;
return ( dist.length2() <= tolerance );
}
static const float tolerance = 0.001;
};
Этот код без проблем компилировался с g ++. Теперь в режиме C ++ 0x (-std = c ++ 0x) компилятор g ++ выдает сообщение об ошибке:
ошибка: 'constexpr' необходим для внутриклассной инициализации статического элемента данных 'толерантность' нецелого типа
Я знаю, что могу определить и инициализировать этот static const
член вне определения класса. Кроме того, нестатический постоянный член данных может быть инициализирован в списке инициализаторов конструктора.
Но есть ли способ инициализировать константу в объявлении класса, как это возможно в PHP или C #?
Обновить
Я использовал static
ключевое слово только потому, что можно было инициализировать такие константы в объявлении класса в g ++. Мне просто нужен способ инициализировать константу в объявлении класса, независимо от того, объявлено оно как static
или нет.
I used static keyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as static or not.
Это неправильный способ решать, быть участникомstatic
или нет. Никогда не позволяйте лексической лени определять семантику вашего кода.That's the wrong way to decide whether a member should be static or not.
Я не согласен. Думаю, для постоянных участников это не имеет значения.static
непостоянный член информацией, зависящей от экземпляра. То, что вы решили, что ваша константа является свойством типа, а не конкретного экземпляра, является причиной сделать этоstatic
, а не потому, что вам понравился ярлык для набора текста.struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };
Все, что может быть,const
должно бытьconst
; это относится как к членам, такstatic
и к нечленамstatic
.Ответы:
В C ++ 11
static
элементыstatic constexpr
данных , не являющиеся членами данных, элементыstatic const
данных и элементы данных интегрального или перечисляемого типа могут быть инициализированы в объявлении класса. напримерstruct X { int i=5; const float f=3.12f; static const int j=42; static constexpr float g=9.5f; };
В этом случае
i
член всех экземпляров классаX
инициализируется5
конструктором, созданным компилятором, аf
член инициализируется значением3.12
.static const
Элемент данныхj
инициализируется42
, аstatic constexpr
член данныхg
инициализируется9.5
.Поскольку
float
иdouble
не относятся к целочисленному или перечислимому типу, такие члены должны бытьconstexpr
или не быть ,static
чтобы инициализатор в определении класса был разрешен.До C ++ 11
static const
инициализаторы в определении класса могли иметь только члены данных целочисленного или перечислимого типа.источник
char const n[3]{'a', 'b', 'c'};
.static const int
ноstatic constexpr float
? что это значитfloat and double are not of integral or enumeration type
?Инициализация статических переменных-членов, отличных от типов const int, не является стандартом C ++ до C ++ 11. Компилятор gcc не предупредит вас об этом (и, тем не менее, создаст полезный код), если вы не укажете этот
-pedantic
параметр. Затем вы должны получить ошибку, похожую на:const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]
Причина этого в том, что стандарт C ++ не определяет, как должна быть реализована плавающая точка, и остается на усмотрение процессора. Чтобы обойти это,
constexpr
были введены и другие ограничения .источник
Да. Просто добавьте
constexpr
ключевое слово, как указано в ошибке.источник
Если вам это нужно только в одном методе, вы можете объявить его локально статическим:
struct equal_vec { bool operator() (const Vector3D& a, const Vector3D& b) const { static const float tolerance = 0.001f; Vector3D dist = b - a; return ( dist.length2() <= tolerance ); } };
источник
Я столкнулся с настоящими проблемами, потому что мне нужен один и тот же код для компиляции с разными версиями g ++ (компилятор GNU C ++). Поэтому мне пришлось использовать макрос, чтобы увидеть, какая версия компилятора используется, а затем действовать соответственно, например
#if __GNUC__ > 5 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr #else #define GNU_CONST_STATIC_FLOAT_DECLARATION const #endif GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;
Это будет использовать 'const' для всего до g ++ версии 6.0.0, а затем использовать 'constexpr' для g ++ версии 6.0.0 и выше. Это предположение о версии, в которой происходит изменение, потому что, честно говоря, я не замечал этого до g ++ версии 6.2.1. Чтобы сделать это правильно, вам, возможно, придется посмотреть на младшую версию и номер патча g ++, поэтому см.
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
для получения подробной информации о доступных макросах.
С gnu вы также можете повсюду использовать 'const', а затем скомпилировать с
-fpermissive
флагом, но это дает предупреждения, и мне нравится, что мои вещи компилируются чисто.Не очень хорошо, потому что это специфично для компиляторов GNU, но я подозреваю, что вы могли бы сделать то же самое с другими компиляторами.
источник