【问题标题】:Elegant initialization of static (member) array with a sequence带有序列的静态(成员)数组的优雅初始化
【发布时间】:2017-02-17 13:34:01
【问题描述】:

我想用预定的顺序初始化一个 big 静态(可能是常量)数组。 在这种特殊情况下,它将是一个正弦表,包含一个数字化的正弦波。

现在,我知道您可以使用以下方法初始化数组:

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

我需要做的就是生成所有正弦值并将它们粘贴到里面,但在我看来这非常丑陋。

是否有 预处理器 指令lambda 函数或用于此目的的东西?

如果做不到这一点,只是在程序开始时计算所有值并将它们分配给静态数组的解决方案?

编辑:

感谢 TemplateRex 来自 c++11: Create 0 to N constexpr array in 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 内联有关。

【问题讨论】:

  • 你可以使用 C++11 中的constexpr 吗?
  • 看看我的老答案 :) stackoverflow.com/questions/35389493/…。纯粹的丑陋!只需定义 2000 个宏就可以了。
  • You have 2x return in fun body :) 我仍然认为这是一个 hack,float[N]std::array&lt;float, N&gt; 不同 :(

标签: c++ arrays static initialization c-preprocessor


【解决方案1】:

您正在寻找的是 C++11 的 constexpr,但您需要模板的递归。

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/

但是,C++ 的标准数学函数是非 constexpr,因此无论如何您都无法使用它们,因此您最好还是按照惯例在某个地方对其进行初始化。

【讨论】:

  • 你知道浮点数不能作为模板non-type参数对吧?
  • 嗯?你的意思是?我认为这里更大的问题是 std::math 都不是非 constexpr
  • 第一个链接的第二个答案有我想要的。复制粘贴提供了工作结果,但我将不得不研究这种难以理解的模板向导数天。谢谢!
  • @SirMate 借助此链接,您可以使用正弦值进行浮点数组初始化吗? :)
  • 是的,虽然我无法将其集成到一个类中,但来自第一个链接的 TemplateRex 的答案适用于我的情况,只需进行最少的修改。
【解决方案2】:

如果您无法使用我不知道的模板技术来实现初始化,这里是另一种更丑陋的方法:

您只需定义 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] << ", ";
}

Demo

如果您只想要 91 个值(每个度数),那么您可以将 TABLE_SIZE 更改为 90,并将宏 SINE91 删除为 SINE2000,并将宏 ALL_91_SINES 定义为 SINE_90

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2011-08-04
    • 2013-04-13
    • 2015-02-18
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多