LINUX.ORG.RU

C++ constexpr + static member того же класса

 ,


0

3

Хочется реализовать что-то типа:

class Foo {
public:
    constexpr Foo(const int value) : value(value) {}    

    constexpr static Foo UNKNOWN = std::numeric_limits<int>::max();
    constexpr static Foo ANY     = UNKNOWN - 1;
    
private:
    int value;
};

Естественно, такой код не собирается, поскольку на момент обьявления constexpr UNKNOWN/ANY тип Foo eще недоконца определен: http://ideone.com/gwCkln

prog.cpp:7:66: error: 'constexpr const Foo Foo::UNKNOWN' has incomplete type
     constexpr static Foo UNKNOWN = std::numeric_limits<int>::max();
                                                                  ^
prog.cpp:8:46: error: 'constexpr const Foo Foo::ANY' has incomplete type
     constexpr static Foo ANY     = UNKNOWN - 1;
                                              ^

Логика компилятора понятна, но ведь статические члены класса не влияют на размер обьекта, а значит ситуацию с куска кода выше теоретически можно разрулить.

Подскажите, можно ли в данной ситуации как-то использовать constexpr а не const.

P.S. Использую g++ 5.3 с -std=c++14

Ответ на: комментарий от KennyMinigun

Static — не член класса.

Член, статический. Тебе же навряд ли нужны именно переменные, под них ещё нужно будет выделять место.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Не понятно с чем ты споришь,

Тогда я совсем не понял первого комментария данной ветки:

Можно сделать функции constexpr, а не члены классa.

А именно: какое отношение данный коментарий имеет к теме.

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

Предлагалось вместо

constexpr static Foo UNKNOWN = std::numeric_limits<int>::max();
использовать аналогичные функции
constexpr static Foo Unknown()
{
    return { std::numeric_limits<int>::max() };
}
Или
enum class EFoo: int {
    Unknown = std::numeric_limits<int>::max(),
    Any = Unknown - 1,
};

class Foo {
public:
    constexpr Foo(EFoo value) : value(static_cast<int>(value)) {}

    // ...
};

Далее EFoo в большинстве выражений само завернётся в Foo неявными преобразованиями если реализуешь нужные операторы для самого Foo, т.е. не везде придётся писать Foo(EFoo::Any).

В твоём варианте под статические переменные придётся выделять место в памяти несмотря на то, что они constexpr. Т.е. нужно будет объявить их ещё и в cpp файле. Придётся так сделать сразу, как только в каком-нибудь коде или шаблоне возьмёшь ссылку или указатель от этих констант. Но т.к. класс у тебя лёгкий, т.е. сам по себе int, то этого можно избежать используя его по значению без оверхеда на копирование.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Спасибо за обьяснение. С функциями хороший вариант. C enum тоже неплохо.

KennyMinigun ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.