Неопределенная ошибка ссылки на статический член данных constexpr

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

undefined reference to `shift7seg::numbers'

Код shift7seg.cpp, показывающий другую функцию, использующую аналогичные определенные массивы

uint8_t shift7seg::convert_char(const char& OGchar){
    uint8_t converted;
    switch (OGchar){
        case 'A':
            converted = capital[0];
            break;
        case 'h':
            converted = lower[3];
            break;
    //more cases removed for posting
    }
    return converted;
}

uint8_t shift7seg::convert_num(const uint8_t& OGnum){
   uint8_t converted;

   if (OGnum<10){
       converted = numbers[OGnum];
   }
   else{
       converted = blank;
   }
   return converted;
}

shift7seg.h, показывающий определения используемых массивов

class shift7seg{
public:
//constructor, choose pins to use as well as display size
    shift7seg(const uint8_t _dataPin,
              const uint8_t _latchPin,
              const uint8_t _clkPin,
              const uint8_t _num_digits);

    static constexpr uint8_t numbers[10] =               // 7 segment values for decimals 0..9
    {
    //TRUTH TABLE    |   0 = segment on
    //ABCDEFGH       |   1 = segment off
    B00000011,  //0  |        A
    B10011111,  //1  |      -----
    B00100101,  //2  |   F |     | B
    B00001101,  //3  |     |  G  |
    B10011001,  //4  |      -----
    B01001001,  //5  |   E |     | C
    B01000001,  //6  |     |     |
    B00011111,  //7  |      -----
    B00000001,  //8  |        D
    B00011001       //9  |
    };

    static constexpr uint8_t capital[13] =
    {
    B00010001,  //A or R, 0
    B00000001,  //B 1
    B01100011,  //C 2
    B00000011,  //D or O, 3
    B01100001,  //E 4
    B01110001,  //F 5
    B01000001,  //G 6
    B10010001,  //H 7
    B10000111,  //J 8
    B11100011,  //L 9
    B00110001,  //P 10
    B01001001,  //S 11
    B10000011  //U or V, 12
    };

    static constexpr uint8_t lower[9] =
    {
    B11000001,  //b 0
    B11100101,  //c 1
    B10000101,  //d 2
    B11010001,  //h 3
    B10011111,  //l 4
    B11010101,  //n 5
    B11000101,  //o 6
    B11110101,  //r 7
    B11000111   //u or v, 8
    };

Диалект C++11. Я не могу в жизни понять, что я сделал не так. Разговор с резиновой уткой пока ничего не дал.

Больше кода ошибки здесь.

more undefined references to `shift7seg::numbers' follow
collect2.exe: error: ld returned 1 exit status
exit status 1

Разве вам не нужно определять статические переменные-члены вне самого определения класса?

Nate Eldredge 09.12.2020 19:40

Этот код должен быть совершенно легальным в C++17. Какой у вас диалект С++?

SergeyA 09.12.2020 19:49

Похоже, этот код компилируется в С++ 11, это единственный компилятор, который я могу использовать в этом случае. как бы это выглядело, определяя статические переменные-члены в другом месте? Будет ли это в моем driver.cpp и присваивать значения как глобальную переменную?

Tanner G 10.12.2020 01:59

За исключением «constexpr» (C++ 11 или выше), я не вижу никаких причин, по которым это не должно компилироваться и связываться с ЛЮБОЙ версией C++! В: Возможно, тот или иной из ваших объектных файлов, ссылающихся на «shift7seg», не был скомпилирован с помощью C++11?

paulsm4 10.12.2020 02:25

Я не знаком с этим типом ошибок, но я пытался его скомпилировать. Я получил еще одну ошибку: /usr/bin/ld: /tmp/cckpICDV.o: warning: relocation against '_ZN9shift7seg7numbersE' in read-only section '.text'. Код становится компилируемым, когда вы меняете OGnum в доступе к массиву numbers на некоторую константу, например 2, однако он также компилируется при переходе на C++17.

niets 10.12.2020 03:11

@Tanner G - рассмотрите возможность простого удаления «constexpr» и сообщите нам, решит ли это проблему.

paulsm4 10.12.2020 03:56

@ paulsm4, что вы ожидаете от этого?

Ryan Haining 10.12.2020 04:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
1 119
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Прежде всего, я думаю, что префикс 0B в этих бинарных литералах, а не B . Во-вторых, вам нужен С++ 17 для его компиляции из-за статического материала constexpr.

цитировать

Если статический член данных объявлен как constexpr, он неявно встроен и не требует повторного объявления в области пространства имен. Это повторное объявление без инициализатора (ранее требовавшееся, как показано выше) по-прежнему разрешено, но не рекомендуется.

от https://en.cppreference.com/w/cpp/language/static

это весь код для arduino, поэтому правильный тег двоичного литерала - B, я посмотрю, смогу ли я заставить его работать без constexpr

Tanner G 10.12.2020 03:54
Ответ принят как подходящий

Где-то в вашем коде вы ODR используетеnumbers, но у вас нет для этого определения.

Вот простая версия вашей проблемы (wandbox):

#include <iostream>
#include <cstdint>

class shift7seg {
  public:
   static constexpr std::uint8_t numbers[10] = {};
};

int main() {
  // taking the address is ODR-use
  std::cout << &shift7seg::numbers[0] << '\n';
}

Возможные решения

  1. скомпилировать с помощью -std=c++17 (или более поздней версии), где все статические элементы данных constexpr неявно встроены и не нуждаются во внешних определениях

  2. Добавьте внешнее определение в свой файл реализации (shift7seg.cpp), как это (wandbox):

constexpr std::uint8_t shift7seg::numbers[10];

Похоже, это проблема, добавление определения вне очереди устранило эту ошибку и принесло другие. отладка продолжается, спасибо

Tanner G 10.12.2020 03:58

Другие вопросы по теме