Используйте препроцессор для генерации значений по умолчанию - PullRequest
6 голосов
/ 05 июля 2019

Я инициализирую очень большой массив с тысячами установленных значений. Я хотел бы, чтобы эти значения устанавливались во время компиляции, а не во время выполнения, поскольку они фиксированы и не изменятся.

Есть ли способ автоматически генерировать эти значения, возможно, используя препроцессор? В настоящее время я генерирую эти значения с помощью другой маленькой программы, затем просто копирую и вставляю значения соответственно.

Вот что я генерирую:

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

1 Ответ

4 голосов
/ 05 июля 2019

Вот пример кода 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;
}

Как видно из вывода сборки , таблица была вычислена во время компиляции.


Поскольку C ++ 17 std::array позволяет использовать оператор [] в стиле constexpr. До C ++ 17, или если вы хотите сохранить не-конструируемость класса по умолчанию, вам придется использовать переменные шаблоны для генерации фигурного инициализатора для массива; этот ответ содержит схему кода, которую вы можете изменить, чтобы использовать алгоритм генерации.

...