1

I would like to initialize a big static (and possibly constant) array with a predetermined sequence. In this particular case it would be a sinetable, containing a digitized sine-wave.

Now, I know you can initialize arrays with:

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

and all I need to do is generate all the sine values and paste them inside, but in my opinion this is incredibly ugly.

Is there a preprocessor directive or a lambda function or something for this?

Failing that, just a solution to calculating all the values at the start of the program and assigning them to the static array?

EDIT:

Thanks to TemplateRex's answer from c++11: Create 0 to N constexpr array in c++ , I have a working solution:

#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); 

Unfortunately I am having difficulties integrating this into a class. Getting error : sinetable::make_array is used before its definition, I'm guessing because static members are defined before static methods. Or maybe it has to do with constexpr being inline.

3
  • 5
    Can you use constexpr from C++11? Commented Oct 8, 2016 at 18:49
  • Check out my very old answer :) stackoverflow.com/questions/35389493/…. Pure ugliness! Just define 2000 macros and you are good. Commented Oct 8, 2016 at 18:57
  • You have 2x return in fun body :) I still consider this a hack, float[N] is not the same as std::array<float, N> :( Commented Oct 8, 2016 at 20:26

2 Answers 2

2

What you're looking for is C++11's constexpr but you'd need either recursion of templates.

c++11: Create 0 to N constexpr array in c++

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

However, C++'s standard math functions are non constexpr so you wouldn't be able to use them anyways so you're probably better off just initializing it conventionally somewhere.

Sign up to request clarification or add additional context in comments.

5 Comments

You know floating point numbers can't be template non-type parameters right?
Hmm? What do you mean? I think the bigger issue here is that none of the std::math are non constexpr
The first link's second answer had what i was looking for. Copy-pasting provided working results, but i will have to study this incromprehensible template-wizarding for days. Thanks!
@SirMate You got working floating-point array initialization with sine values thanks to this link? :)
Yes, while i am having trouble integrating this into a class, the answer from TemplateRex from the first link works for my case with minimal modifications.
0

If you can't manage to achieve the initialization with template techniques that I don't know about, here is alternative, uglier approach:

You just define 2001 macros:

#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 

And just use it this way:

#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] << ", "; } 

Demo

If you want only 91 values (of every degree), then you can change TABLE_SIZE to 90, and remove macros SINE91 to SINE2000, and define macro ALL_91_SINES as SINE_90.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.