微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在c ++ 17中生成内联constexpr普通数组数组 大括号初始化器带有 constexpr 的结构最后一个数组数组

如何解决如何在c ++ 17中生成内联constexpr普通数组数组 大括号初始化器带有 constexpr 的结构最后一个数组数组

问题

我正在用 c++17 编写一个软件,对于它来说,性能绝对是至关重要的。我想在数组本身的数组中使用几个关键函数常量。重要的是,这两个数组都可以通过这样(或类似)方式的整数值访问:
int main()
{
    for (int i = 0; i < size_of_A ; i++)
    {
        for (int j = 0; j < size_of_B_in_A(i); j++)
        {
            std::cout << A[i][j];
        }
    }
}

假设某个函数 int f(a,b)

A
{
    // B1
    {
        f(1,1),f(1,2),3),...
        f(1,large number)
    },// B2
    {
        f(2,...
        f(2,some other large number)
    },... etc
}

扭曲

每个内部数组可能具有不同的大小,我们将存储在其他地方,我们必须在编译时找到大小。我宁愿不使用 std::vector 因为它们被假定 slightly slower 。 此外,我认为 std::vector 将存储在堆上,这在我的特定情况下将是一个性能问题。 此外, std::vector cannot be used as "inline constexpr" 这将是必要的,因为我希望这些数组中的大量值永远不会改变。我每次都可以重新编译所有这些值,但不会通过策略将它们保存在外部文件中,因为我要遵循严格的编码风格。

我的尝试

大括号初始化器

// A.hh

#pragma once

#include <iostream>

void test1();
void test2();

inline constexpr int B1[1] = {1};
inline constexpr int B2[2] = {2,3};
inline constexpr int B3[3] = {4,5,6};

inline constexpr const int *A[3] = {B1,B2,B3};

// main.cc

#include "A.hh"

int main()
{
    std::cout << "values : ";
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            std::cout << A[i][j];
        }
    }

    std::cout << "\n\naddress test : \n";
    std::cout << &A << '\n';
    test1();
    test2();
}
// somewhere.cc

#include "A.hh"

void test1()
{
    std::cout << &A << '\n';
}

// elsewhere.cc

#include "A.hh"

void test2()
{
    std::cout << &A << '\n';
}

打印:

./a.out
values : 123456

address test :
0x56180505cd70
0x56180505cd70
0x56180505cd70

所以A没有被复制到main.cc、where.cc和others.cc中,这很好。我想走得更远,能够创造大量的价值。

带有 constexpr 的结构

使用提示找到 here ,我这样做是为了能够在数组构造期间执行操作。
// B.hh

#pragma once

#include <iostream>

template <int N>
struct X
{
    int arr[N];
    constexpr X(): arr()
    {
        for (int i = 0; i < N; i++)
        {
            arr[i] = i % 3;
        }
    }
};

inline constexpr auto A = X<500>();
// main.cc

#include "B.hh"

int main()
{
    for (int i = 0; i < 500; i++)
    {
        std::cout << A.arr[i];
    }
}

毫无疑问地打印出来

012012 (etc)...

最后一个数组数组

这就是我被卡住的地方
#pragma once

#include <iostream>

template <int N>
struct sub_array
{
    int arr[N];
    constexpr sub_array() : arr()
    {
        for (int i = 0; i < N; i++)
        {
            arr[i] = i;
        }
    }
};

struct array
{
    sub_array</*what here ?*/> arr[100];

    constexpr array() : arr()
    {
        for (int i = 0; i < 100; i++)
        {
            int size = i * 2; // a very large number

            // the value of 'size' is not usable in a constant expression
            //
            // I see why it is,but I can't think of any other way
            arr[i] = sub_array<size>;
        }
    }
};

inline constexpr array A = array();

我怎样才能构建这样的数组?

感谢您的时间和考虑。

解决方法

只需使用std::array<std::span<int>,N>,它是不同大小的跨度的固定大小数组。要生成它,请使用 std::index_sequence

标题:

constexpr std::size_t size_of_A = 500;
extern const std::array<const std::span<const int>,size_of_A>& A;

实施:

constexpr std::size_t size_of_B_in_A(std::size_t i) { return i%10+1;}
constexpr int f(std::size_t i,std::size_t j) {return static_cast<int>(i%(j+1));}

template <int I,int N>
struct B
{
    std::array<int,N> arr;
    explicit constexpr B()
    {
        for (int j = 0; j < N; j++)
            arr[j] = f(I,j);
    }
    constexpr operator const std::span<const int>() const {return {arr};}
};

template<class index_sequence>
class BGen;
template<std::size_t... I>
struct BGen<std::integer_sequence<std::size_t,I...>> {
    static constexpr std::tuple<B<I,size_of_B_in_A(I)>...> bs{};
    static constexpr std::array<const std::span<const int>,sizeof...(I)> A {std::get<I>(bs)...};
};
const std::array<const std::span<const int>,size_of_A>& A 
    = BGen<decltype(std::make_index_sequence<size_of_A>{})>::A;

用法:

int main()
{
    for (unsigned i = 0; i < A.size() ; i++)
    {
        for (unsigned j = 0; j < A[i].size(); j++)
        {
            std::cout << A[i][j];
        }
    }
}

http://coliru.stacked-crooked.com/a/d68b0e9fd6142f86


但是,退一步:此解决方案不是解决此问题的正常方法。因为都是constexpr,所以这都是数据而不是代码。因此,性能最好的解决方案是两个程序。一个生成数据并将其保存到一个文件中,该文件随(内部?)您的程序。然后你的程序简单地将文件映射到内存中,并直接使用数据。

,

这是一种实现 constexpr 锯齿状数组的方法,该数组可以在没有中间体的情况下进行初始化。它确实需要将行大小作为模板参数列出,但也有一些方法可以使这更容易,这取决于在编译时如何知道行大小。

#include <tuple>
#include <array>
#include <utility>

template <std::size_t ...Sizes>
struct jagged_array
{
    const std::tuple<std::array<int,Sizes>...> data;

    static constexpr std::size_t num_rows = sizeof...(Sizes);
    static constexpr std::size_t length[num_rows]{Sizes...};
    int const* const row_ptr[num_rows];

    template <std::size_t ...I>
    constexpr jagged_array(std::index_sequence<I...>,const std::array<int,Sizes>& ...arrs)
    : data{arrs...},row_ptr{&std::get<I>(data)[0]...} {}

    constexpr jagged_array(const std::array<int,Sizes>& ...arrs)
    : jagged_array(std::make_index_sequence<num_rows>{},arrs...)
    {}

    constexpr int const* operator[](std::size_t idx) const
    { return row_ptr[idx]; }
};

inline constexpr jagged_array<2,4> jarr = {{2,3},{4,5,6,7}};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。