- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我发现了两种在编译时初始化整数数组的好方法 here和 here .
不幸的是,两者都不能直接转换为初始化 float 组;我发现我不太适合模板元编程,无法通过反复试验来解决这个问题。
首先让我声明一个用例:
constexpr unsigned int SineLength = 360u;
constexpr unsigned int ArrayLength = SineLength+(SineLength/4u);
constexpr double PI = 3.1415926535;
float array[ArrayLength];
void fillArray(unsigned int length)
{
for(unsigned int i = 0u; i < length; ++i)
array[i] = sin(double(i)*PI/180.*360./double(SineLength));
}
如您所见,就可用信息而言,此数组可以声明为constexpr
。
但是,对于链接的第一种方法,生成器函数 f
必须如下所示:
constexpr float f(unsigned int i)
{
return sin(double(i)*PI/180.*360./double(SineLength));
}
这意味着需要一个 float
类型的模板参数。这是不允许的。
现在,第一个想到的想法是将 float 存储在一个 int 变量中——数组索引在计算后没有任何变化,因此假装它们是另一种类型(只要 byte-长度相等)完全没问题。
但是请看:
constexpr int f(unsigned int i)
{
float output = sin(double(i)*PI/180.*360./double(SineLength));
return *(int*)&output;
}
不是有效的 constexpr
,因为它包含的不仅仅是 return 语句。
constexpr int f(unsigned int i)
{
return reinterpret_cast<int>(sin(double(i)*PI/180.*360./double(SineLength)));
}
也不行;尽管人们可能认为 reinterpret_cast
确实做了这里需要的事情(即什么都没有),但它显然只适用于指针。
按照第二种方法,生成器函数看起来会略有不同:
template<size_t index> struct f
{
enum : float{ value = sin(double(index)*PI/180.*360./double(SineLength)) };
};
本质上是相同的问题:该枚举不能是 float
类型,并且该类型不能被屏蔽为 int
。
现在,尽管我只是在“假装 float
是一个 int
”的路径上解决了这个问题,但我实际上并不喜欢这条路径(除了它不工作)。我更喜欢一种将 float
实际处理为 float
的方式(并且将 double
处理为 double
),但我看不出有什么办法可以绕过强加的类型限制。
可悲的是,关于这个问题有很多问题,这些问题总是指整数类型,淹没了对这个专门问题的搜索。同样,关于将一种类型屏蔽为另一种类型的问题通常不会考虑 constexpr
或模板参数环境的限制。
参见 [1] [2] [3]和 [4] [5]等等
最佳答案
假设您的实际目标是使用一种简洁的方法来初始化 float 数组,并且它不一定拼写为 float array[N]
或 double array[N]
而是std::array<float, N> array
或 std::array<double, N> array
这是可以做到的。
数组类型的意义在于std::array<T, N>
可以复制 - 不像 T[N]
.如果可以复制,则可以通过函数调用获取数组的内容,例如:
constexpr std::array<float, ArrayLength> array = fillArray<N>();
这对我们有什么帮助?好吧,当我们可以调用一个以整数作为参数的函数时,我们可以使用 std::make_index_sequence<N>
使用 std::size_t
的编译时序列来自 0
至 N-1
.如果我们有,我们可以使用基于索引的公式轻松初始化数组,如下所示:
constexpr double const_sin(double x) { return x * 3.1; } // dummy...
template <std::size_t... I>
constexpr std::array<float, sizeof...(I)> fillArray(std::index_sequence<I...>) {
return std::array<float, sizeof...(I)>{
const_sin(double(I)*M_PI/180.*360./double(SineLength))...
};
}
template <std::size_t N>
constexpr std::array<float, N> fillArray() {
return fillArray(std::make_index_sequence<N>{});
}
假设用于初始化数组元素的函数实际上是一个constexpr
表达式,这种方法可以生成一个 constexpr
.函数const_sin()
这是为了演示目的而做的,但显然,它没有计算 sin(x)
的合理近似值。 .
评论表明到目前为止的答案并不能完全解释发生了什么。因此,让我们将其分解为易于理解的部分:
目标是生成一个 constexpr
数组填充了合适的值序列。但是,数组的大小应该可以通过调整数组大小轻松更改 N
.也就是说,从概念上讲,目标是创造
constexpr float array[N] = { f(0), f(1), ..., f(N-1) };
在哪里f()
是生成 constexpr
的合适函数.例如,f()
可以定义为
constexpr float f(int i) {
return const_sin(double(i) * M_PI / 180.0 * 360.0 / double(Length);
}
但是,输入对 f(0)
的调用, f(1)
等需要随着 N
的每次更改而更改.因此,应该进行与上述声明基本相同的操作,但无需额外输入。
解决方案的第一步是替换 float[N]
通过 std:array<float, N>
: 在 std::array<float, N>
时无法复制内置数组可以复制。也就是说,初始化可以委托(delegate)给参数化为 N
的函数。 .也就是说,我们会使用
template <std::size_t N>
constexpr std::array<float, N> fillArray() {
// some magic explained below goes here
}
constexpr std::array<float, N> array = fillArray<N>();
在函数中,我们不能简单地遍历数组,因为非 const
下标运算符不是 constexpr
.相反,数组需要在创建时进行初始化。如果我们有一个参数包 std::size_t... I
代表序列0, 1, .., N-1
我们可以做
std::array<float, N>{ f(I)... };
因为扩展实际上等同于打字
std::array<float, N>{ f(0), f(1), .., f(N-1) };
那么问题就变成了:如何得到这样的参数包?我不认为它可以直接在函数中获取,但可以通过使用合适的参数调用另一个函数来获取。
使用别名 std::make_index_sequence<N>
是类型 std::index_sequence<0, 1, .., N-1>
的别名.实现的细节有点神秘,但是 std::make_index_sequence<N>
, std::index_sequence<...>
, friends 是 C++14 的一部分(它们是由 N3493 基于例如 this answer from me 提出的)。也就是说,我们需要做的就是调用一个参数类型为std::index_sequence<...>
的辅助函数。并从那里获取参数包:
template <std::size_t...I>
constexpr std::array<float, sizeof...(I)>
fillArray(std::index_sequence<I...>) {
return std::array<float, sizeof...(I)>{ f(I)... };
}
template <std::size_t N>
constexpr std::array<float, N> fillArray() {
return fillArray(std::make_index_sequence<N>{});
}
此函数的[未命名]参数仅用于具有参数包std::size_t... I
被推导。
关于c++ - 如何在编译时初始化一个 float 组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34310866/
我是 Spring 新手,这就是我想要做的事情: 我正在使用一个基于 Maven 的库,它有自己的 Spring 上下文和 Autowiring 字段。 它的bean配置文件是src/test/res
我在我的测试脚本中有以下列表初始化: newSequenceCore=["ls", "ns", "*", "cm", "*", "ov", "ov", "ov", "ov", "kd"] (代表要在控
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Class construction with initial values 当我查看 http://en.
我得到了成员变量“objectCount”的限定错误。编译器还返回“ISO C++ 禁止非常量静态成员的类内初始化”。这是主类: #include #include "Tree.h" using n
我有如下所示的a.h class A { public: void doSomething()=0; }; 然后我有如下所示的b.h #include "a.h" class b: publi
我需要解析 Firebase DataSnapshot (一个 JSON 对象)转换成一个数据类,其属性包括 enum 和 list。所以我更喜欢通过传递 DataSnapshot 来手动解析它进入二
我使用 JQuery 一段时间了,我总是使用以下代码来初始化我的 javascript: $(document).ready( function() { // Initalisation logic
这里是 Objective-C 菜鸟。 为什么会这样: NSString *myString = [NSString alloc]; [myString initWithFormat:@"%f", s
我无法让核心数据支持的 NSArrayController 在我的代码中正常工作。下面是我的代码: pageArrayController = [[NSArrayController alloc] i
我对这一切都很陌生,并且无法将其安装到我的后端代码中。它去哪里?在我的页脚下面有我所有的 JS? 比如,这是什么意思: Popup initialization code should be exec
这可能是一个简单的问题,但是嘿,我是初学者。 所以我创建了一个程序来计算一些东西,它目前正在控制台中运行。我决定向其中添加一个用户界面,因此我使用 NetBeans IDE 中的内置功能创建了一个 J
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
据我所知, dependentObservable 在声明时会进行计算。但如果某些值尚不存在怎么办? 例如: var viewModel ={}; var dependentObservable1 =
我正在阅读 POODR 这本书,它使用旧语法进行默认值初始化。我想用新语法实现相同的功能。 class Gear attr_reader :chainring, :cog, :wheel de
我按照 polymer 教程的说明进行操作: https://www.polymer-project.org/3.0/start/install-3-0 (我跳过了可选部分) 但是,在我执行命令“po
很抱歉问到一个非常新手的Kotlin问题,但是我正在努力理解与构造函数和初始化有关的一些东西。 我有这个类和构造函数: class TestCaseBuilder constructor(
假设我们有一个包含 30 列和 30 行的网格。 生命游戏规则简而言之: 一个小区有八个相邻小区 当一个细胞拥有三个存活的相邻细胞时,该细胞就会存活 如果一个细胞恰好有两个或三个活的相邻细胞,那么它就
我是 MQTT 和 Android 开放附件“AOA” 的新手。在阅读教程时,我意识到,在尝试写入 ByteArrayOutputStream 类型的变量之前,应该写入 0 或 0x00首先到该变量。
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
我有一个inotify /内核问题。我正在使用“inotify” Python项目进行观察,但是,我的问题仍然是固有的关于inotify内核实现的核心。 Python inotify项目处理递归ino
我是一名优秀的程序员,十分优秀!