Не может ли класс иметь статические константные члены-члены?
Этот код дает мне ошибку неполного типа.
В чем проблема? Не разрешено ли для класса иметь статические члены экземпляра?
Есть ли способ достичь того же результата?
struct Size
{
const unsigned int width;
const unsigned int height;
static constexpr Size big = { 480, 240 };
static constexpr Size small = { 210, 170 };
private:
Size( ) = default;
};
Ответы
Ответ 1
Есть ли способ добиться того же результата?
В результате "того же результата" вы конкретно намерены constexpr
-ness
Size::big
и Size::small
? В этом случае, возможно, это будет достаточно близко:
struct Size
{
const unsigned int width = 0;
const unsigned int height = 0;
static constexpr Size big() {
return Size { 480, 240 };
}
static constexpr Size small() {
return Size { 210, 170 };
}
private:
constexpr Size() = default;
constexpr Size(int w, int h )
: width(w),height(h){}
};
static_assert(Size::big().width == 480,"");
static_assert(Size::small().height == 170,"");
Ответ 2
Класс допускает статический член того же типа. Тем не менее, класс не завершен до конца его определения, а объект не может быть определен с неполным типом. Вы можете объявить объект с неполным типом и определить его позже, где он будет завершен (вне класса).
struct Size
{
const unsigned int width;
const unsigned int height;
static const Size big;
static const Size small;
private:
Size( ) = default;
};
const Size Size::big = { 480, 240 };
const Size Size::small = { 210, 170 };
см. здесь: http://coliru.stacked-crooked.com/a/f43395e5d08a3952
Это не работает для членов constexpr
.
Ответ 3
В качестве обходного пути вы можете использовать отдельный базовый класс, определение которого завершено при определении констант в производном классе.
struct size_impl
{
//data members and functions here
unsigned int width;
unsigned int height;
};
struct size: public size_impl
{
//create the constants as instantiations of size_impl
static constexpr size_impl big{480,240};
static constexpr size_impl small{210,170};
//provide implicit conversion constructor and assignment operator
constexpr size(const size_impl& s):size_impl(s){}
using size_impl::operator=;
//put all other constructors here
};
//test:
constexpr size a = size::big;
Вы можете поместить базовый класс в отдельное пространство имен, чтобы скрыть его определение, если хотите.
Код компилируется с помощью clang и gcc