Подтвердить что ты не робот

Не может ли класс иметь статические константные члены-члены?

Этот код дает мне ошибку неполного типа. В чем проблема? Не разрешено ли для класса иметь статические члены экземпляра? Есть ли способ достичь того же результата?

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;
};
4b9b3361

Ответ 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