Arhn - архитектура программирования

Как получить constexpr `.size ()` нестатического члена std :: array

Учитывая, что std::array<T,N>::size - constexpr, в приведенном ниже фрагменте

  • Почему имеет значение, что Foo1::u не является членом static? Тип известен во время компиляции, как и его size().
  • Что не так с Foo2::bigger()?

Листинг:

// x86-64 gcc 10.1
// -O3 --std=c++20 -pedantic -Wall -Werror

#include <array>
#include <cstdint>

union MyUnion {
    std::array<uint8_t,32> bytes;
    std::array<uint32_t,8> words;
};

struct Foo1 {
    MyUnion u;
    static constexpr size_t length {u.bytes.size()};
        //invalid use of non-static data member 'Foo1::u'
};

struct Foo2 {
    MyUnion u;
    size_t x;
    consteval int8_t length() const { return u.bytes.size(); };
    bool bigger() const { return x > length(); }
        //'this' is not a constant expression
};

Я хотел бы сохранить длину std :: array в объявлении MyUnion и не прибегать к

constexpr size_t LEN {32};
union MyUnion {
    std::array<uint8_t,LEN> bytes;
    std::array<uint32_t,LEN/4> words;
};

  • Один вопрос на вопрос stackoverflow.com, пожалуйста. Две ошибки компиляции имеют разные причины. 07.02.2021
  • Кстати, вы не можете использовать words, если вы инициализировали bytes, поскольку у них нет общей начальной последовательности 07.02.2021
  • Представьте, что статическая функция ломается из-за того, что вы изменили нестатический член класса. Это не хорошо. 08.02.2021

Ответы:


1

Эти ситуации немного разные.

В первом:

    static constexpr size_t length {u.bytes.size()};
        //invalid use of non-static data member 'Foo1::u'

Вы пытаетесь получить доступ к нестатическому члену данных без объекта. Это просто не то, что ты можешь сделать. С этим выражением должно быть что-то Foo1. В контексте нестатической функции-члена это неявно будет this->u, но там все равно должен быть какой-то объект. Есть только одно исключение: вам разрешено писать sizeof(Foo1::u).


Во втором:

    consteval int8_t length() const { return u.bytes.size(); };

Здесь указатель this сам по себе не является постоянным выражением (мы не знаем, на что он указывает), поэтому доступ к чему-либо через него не выполняется. Это часть более широкого случая константных выражений, использующих неизвестные ссылки, и это не влияет на постоянство выражения (см. Мое сообщение в блоге на проблема с размером массива constexpr). Недавно я написал статью по этой теме, в которой основное внимание уделялось ссылкам, но this - это узкое расширение поверх что.

В любом случае, сейчас это тоже не сработает, потому что все должно быть постоянным. Поэтому вам придется прибегнуть к тому, что вы предлагаете: выставить нужную константу отдельно.

07.02.2021

2

Я рекомендую в первую очередь использовать переменную для определения размера:

union MyUnion {
    static constexpr std::size_t size = 32;

    using byte = std::uint8_t;
    using word = std::uint32_t;
    
    std::array<byte, size> bytes;
    std::array<word, size / sizeof(word)> words;
};

struct Foo1 {
    using Union = MyUnion;
    Union u;
    static constexpr std::size_t length = Union::size;
};

Почему имеет значение, что Foo1 :: u не является статическим членом?

Доступ к нестатическим членам можно получить только внутри функций-членов.


Я рекомендую использовать std::variant вместо union. Это намного проще в использовании.

07.02.2021

3

Вы можете получить его прямо из типа

// direct
consteval static auto length() { return std::tuple_size<decltype(MyUnion::bytes)>::value; }
// with indirection
consteval static auto length() { return std::tuple_size<std::decay_t<decltype(u.bytes)>>::value; }

Или вы можете сделать это, создав новый экземпляр.

// direct
consteval static auto length() { return MyUnion{.bytes={}}.bytes.size(); }
// just the member + indirection
consteval static auto length() { return decltype(u.bytes){}.size(); }

За ошибки в коде

недопустимое использование нестатического члена данных 'Foo1 :: u'

означает, что вы не можете использовать нестатический член данных u без экземпляра (например, внутри функции члена static).

'this' не является постоянным выражением *

означает, что вы не можете позвонить this.length() (просто потому, что он consteval, но this здесь нет)

Почему? потому что это то, что говорит стандарт, иначе нет причин использовать спецификатор constexpr, потому что компилятор может сделать это, не так ли?


Связанный вопрос:

07.02.2021
  • конечно, вы также можете получить размер из decltype(u.bytes) с помощью некоторого шаблона, если вы уверены, что это std::array, см. также Почему не 't std :: array :: size static? 08.02.2021
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..