Я хотел бы инициализировать большой статический (и, возможно, постоянный) массив с заранее определенной последовательностью.
В этом конкретном случае это будет синусоидальный файл, содержащий оцифрованную синусоидальную волну.
Теперь я знаю, что вы можете инициализировать массивы с помощью:
#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
быть встроенным.
То, что вы ищете, это constexpr в C ++ 11, но вам понадобится либо рекурсия шаблонов.
c ++ 11: создание массива constexpr от 0 до N в c ++
Однако стандартные математические функции C ++ не являются constexpr, поэтому вы не сможете их использовать в любом случае, поэтому вам, вероятно, лучше просто инициализировать их где-нибудь условно.
Если вам не удается добиться инициализации с помощью шаблонных методов, о которых я не знаю, вот альтернативный, более уродливый подход:
Вы просто определяете макросы 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
,