Цикл над массивом constexpr

#c #for-loop #constexpr

#c #for-цикл #constexpr

Вопрос:

У меня есть следующие файлы:

test.hpp

 class Test {
    static constexpr const char* array[] {
        "hello",
        "world",
        "!"
    };
  public:   
    void do_stuff();
    
};
  

test.cpp

 void Test::do_stuff() {
  for(int i = 0; i < 3;   i) {
    std::cout << array[i];
  }
}

int main() {
  Test object;
  object.do_stuff();

}
  

Это завершается ошибкой со следующей ошибкой связывания:

неопределенная ссылка на `Test::array’

Итак, как я могу определить массив constexpr, а затем выполнить итерацию по нему?

Комментарии:

1. Если вы используете c , предпочитайте std::array старые массивы на C.

2. Это должно быть связано просто отлично — какой компилятор вы используете? И какой языковой стандарт вы предполагаете, вы передаете -std=c ?? аргумент?

3. посмотрите здесь: godbolt.org/z/9abK4h та же ошибка, она исчезает, когда вы указываете --std=c 17

Ответ №1:

static участникам требуется автономное объявление или явное inline :

Из C 17:

 inline static constexpr const char* array[] {
  

Другое решение:

 #include <iostream>

class Test {
    static constexpr const char* array[] {
        "hello",
        "world",
        "!"
    };
  public:   
    void do_stuff();
    
};

constexpr char* Test::array[];

void Test::do_stuff() {
  for(int i = 0; i < 3;   i) {
    std::cout << array[i];
  }
}

int main() {
  Test object;
  object.do_stuff();

}
  

Комментарии:

1. Вы хотите static constexpr char const* array и нет static constexpr char* array . Это constexpr для массива, но const (который есть у OP, но вы удалили) — для указателя на константу . В настоящее время у вас есть массив указателей constexpr, которые могут изменять то, на что они указывают.

2. добавлен обратно const

Ответ №2:

Рассмотрите возможность использования std::array вместо необработанного массива:

 #include <array>
#include <iostream>

struct Test {
    static constexpr std::array<const char*, 2> arr{"hello", "world"};
};

// Out-of class definition.
const std::array<const char*, 2> Test::arr;

int main() {
    for (const auto c : Test::arr) { std::cout << c << " "; }
    // hello world
}
  

обратите внимание на определение вне класса, необходимое, если arr используется элемент статических данных ODR.

Комментарии:

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

2. Необходимое там «2» немного разрушает std::array, ИМХО. В тот момент, когда я поймал себя на подсчете элементов, я вернул использование std::array таким образом.