Элегантная инициализация статического (члена) массива с последовательностью

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

Теперь я знаю, что вы можете инициализировать массивы с помощью:

#define TABLE_SIZE 2000
static float table[TABLE_SIZE] = { 0 , 0.124 , 0.245 , ...  }

и все, что мне нужно сделать, это сгенерировать все значения синусов и вставить их внутрь, но, на мой взгляд, это невероятно некрасиво.

Есть ли препроцессор директива или лямбда функция или что-то для этого?

В противном случае, просто решение для вычисления всех значений в начале программы и присвоения их статическому массиву?

РЕДАКТИРОВАТЬ:

Благодаря ответу TemplateRex от c ++ 11: создание массива constexpr от 0 до N в c ++
, У меня есть рабочее решение:

#define TABLE_SIZE 2000
template<class Function, std::size_t... Indices>
constexpr auto make_array_helper(Function f, std::index_sequence<Indices...>)
-> std::array<typename std::result_of<Function(std::size_t)>::type, sizeof...(Indices)>
{
return {{ f(Indices)... }};
}

template<int N, class Function>
constexpr auto make_array(Function f)
-> std::array<typename std::result_of<Function(std::size_t)>::type, N>
{
return make_array_helper(f, std::make_index_sequence<N>{});
}

constexpr float fun(double x) { return (float)sin(((double)x / (double)TABLE_SIZE) * M_PI * 2.0); }

static constexpr auto sinetable = make_array<TABLE_SIZE>(fun);

К сожалению, у меня возникают трудности при интеграции этого в класс.
Получение ошибки: sinetable::make_array is used before its definitionЯ предполагаю, потому что статические члены определены перед статическими методами. Или, может быть, это связано с constexpr быть встроенным.

1

Решение

То, что вы ищете, это constexpr в C ++ 11, но вам понадобится либо рекурсия шаблонов.

c ++ 11: создание массива constexpr от 0 до N в c ++

http://fendrich.se/blog/2012/11/22/compile-time-loops-in-c-plus-plus-11-with-trampolines-and-exponential-recursion/

Однако стандартные математические функции C ++ не являются constexpr, поэтому вы не сможете их использовать в любом случае, поэтому вам, вероятно, лучше просто инициализировать их где-нибудь условно.

1

Другие решения

Если вам не удается добиться инициализации с помощью шаблонных методов, о которых я не знаю, вот альтернативный, более уродливый подход:

Вы просто определяете макросы 2001 года:

#include <cmath>

#define TABLE_SIZE 2000

#define SINE0 0.0f
#define SINE1 SINE0 ,std::sin( 1.0f * M_PI / ( 2 * TABLE_SIZE) )
#define SINE2 SINE1 ,std::sin( 2.0f * M_PI / ( 2 * TABLE_SIZE) )
#define SINE3 SINE2 ,std::sin( 3.0f * M_PI / ( 2 * TABLE_SIZE) )
//...

//...
#define SINE1998 SINE1997 ,std::sin( 1998.0f * M_PI / ( 2 * TABLE_SIZE) )
#define SINE1999 SINE1998 ,std::sin( 1999.0f * M_PI / ( 2 * TABLE_SIZE) )
#define SINE2000 SINE1999 ,std::sin( 2000.0f * M_PI / ( 2 * TABLE_SIZE) )

#define ALL_2001_SINES SINE2000

И просто используйте это так:

#include <iostream>

#include "file_with_macros.hpp" // contains above macros and includes <cmath>

static float const table[TABLE_SIZE+1] = {ALL_2001_SINES}; // + 1 because of inclusion of
// both borders 0.0f and M_PI/2

int main()
{
for(int i=0; i<TABLE_SIZE+1; ++i)
std::cout << table[i] << ", ";
}

демонстрация

Если вы хотите только 91 значение (каждой степени), то вы можете изменить TABLE_SIZE до 90, и удалить макросы SINE91 в SINE2000и определить макрос ALL_91_SINES как SINE_90,

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector