使用预处理器生成默认值

Posted

技术标签:

【中文标题】使用预处理器生成默认值【英文标题】:Use Preprocessor to Generate Default Values 【发布时间】:2019-07-05 03:24:15 【问题描述】:

我正在初始化一个包含数千个设置值的非常大的数组。我希望在编译时而不是运行时设置这些值,因为它们是固定的并且不会改变。

有没有办法自动生成这些值,也许使用预处理器?目前我正在使用另一个小程序生成这些值,然后分别简单地复制和粘贴这些值。

这是我正在生成的:

class MyClass

public:
    MyClass(int x, int y, int z) : X(x), Y(y), Z(z) 

    int X, Y, Z;
;

std::vector<MyClass> my_vector
    #include "my_vector_default_values.h"
;

my_vector_default_values.h

MyClass(0, 0, 1),
MyClass(0, 0, 2),
MyClass(0, 0, 3),
MyClass(0, 0, 4),
// etc... for thousands of lines
// ...

编辑:

我生成的实际值如下(这是C#程序):

var sb = new StringBuilder();

var sizeX = 32;
var sizeY = 32;
var sizeZ = 32;

for (var x = 0; x < sizeX; x++)

    for (var y = 0; y < sizeY; y++)
    
        for (var z = 0; z < sizeZ; z++)
        
            sb.AppendLine($"MyClass(x, y, z),");
        
    


var s = sb.ToString();

【问题讨论】:

忘掉预处理器吧。在 C++ 中,最好使用 constexpr 初始化程序来执行此操作。显然,复杂度取决于计算的复杂度。 OTOH,如果可行,我认为您当前的策略没有任何问题,但我不明白为什么您不直接写入将#include 的文件。这样,您可以将文件生成自动化作为构建过程的一部分,并避免干预复制和粘贴。 如果性能是一个问题,如果您从 my_vector_default_values.h 中删除所有换行符,您可能会获得非常小的加速。 “有没有办法自动生成这些值”如果你告诉我们你用哪种方式生成它们,我们可能会说些什么。否则它需要心灵感应机器,但今天无法使用。 编辑令人困惑,原始示例询问int,但编辑中有某种类调用(这对解决方案有很大影响) 好的,如果 OP 能够澄清这一点会很好(术语“默认值”通常意味着可以在运行时设置其他值,而选择 vector 表明他们想要运行时调整大小) 【参考方案1】:

这里是一些示例 C++17 代码,如果你可以使类默认可构造:

#include <array>

const size_t gX = 32, gY = 32, gZ = 32;

class MyClass

public:
    int X, Y, Z;
;

constexpr std::array<MyClass, gX*gY*gZ> gen()

    std::array<MyClass, gX*gY*gZ> r;
    size_t n = 0;

    for (int x = 0; x < gX; ++x)
        for (int y = 0; y < gY; ++y)
            for (int z = 0; z < gZ; ++z)
                r[n++] =  x, y, z ;

    return r;


extern constexpr auto global = gen();

int main()

    return global[35].Z;

从the assembly output 可以看出,该表是在编译时计算的。


由于 C++17 std::array 允许 operator[] 以 constexpr 方式使用。在 C++17 之前,或者如果你想保留类的非默认可构造性,你必须使用可变参数模板来为数组生成一个花括号初始化器; this answer 提供了一个代码大纲,您可以修改它以使用您的生成算法。

【讨论】:

以上是关于使用预处理器生成默认值的主要内容,如果未能解决你的问题,请参考以下文章

用CMake设置Visual Studio工程中预处理器定义值

使用预处理器指令生成成员名称?

Kaggle泰坦尼克号数据机器学习实战:从缺失值处理数据探索性分析组合特征生成到多模型构建

css的预处理器less的混合函数的用法

95-874-040-源码-批处理-Flink批处理优化器值成本估算

95-874-040-源码-批处理-Flink批处理优化器值成本估算