c++c++11arduinoconstexprundefined-reference

Undefined reference error to static constexpr data member


I'm very confused as to what is wrong here. I am getting an undefined reference error to an array I have defined the same way as two others which are not throwing errors elsewhere in the code.

undefined reference to `shift7seg::numbers'

shift7seg.cpp code showing other function using similarly defined arrays being used

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 showing definitions of arrays being used

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

Dialect is C++11 I cannot for the life of me figure out what I have done wrong. Talking to the rubber duck has done nothing so far.

More of the error code is here.

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

Solution

  • Somewhere in your code you are ODR-using numbers but you don't have a definition for it.

    Here's a simple version of your problem (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';
    }
    

    Possible solutions are

    1. compile with -std=c++17 (or later) where all static constexpr data members are implicitly inline and don't need out-of-line definitions

    2. Add an out-of-line definition in your implementation file (shift7seg.cpp) like this (wandbox):

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