Инициализация члена const в объявлении класса В C++
в 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 или нет.
6 ответов:
в C++11, не
staticданные-члены,static constexprданные-члены, иstatic constэлементы данных типа integral или перечисления могут быть инициализированы в объявлении класса. например,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элементы данных типа integral или перечисления могут иметь инициализаторы в определении класса.
инициализация статических переменных-членов, отличных от типов const int, не является стандартным C++ до C++11. Компилятор gcc не предупредит вас об этом (и тем не менее создаст полезный код), если вы не укажете . Затем вы должны получить ошибку, похожую на:
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был введенный.
если он вам нужен только в одном методе, вы можете объявить его локально статическим:
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, но я подозреваю, что вы можете сделать то же самое с другими компиляторами.
Ну, не совсем прямой ответ, но какая-то конкретная причина не использовать макрос?
#define tolerance 0.001 struct equal_vec { bool operator() (const Vector3D& a, const Vector3D& b) const { Vector3D dist = b - a; return ( dist.length2() <= tolerance ); } };не совсем хорошая практика C#, но ИМХО совершенно законно в C++.