有没有办法访问结构的第n个元素?

我有指针结构,其中指针是任意类型但在编译时已知。

struct ptrs
{
    int* a;
    const char** b;
    int* c;
    float* d;
};

鉴于它们都是指针,它们的长度都相同。有没有办法可以访问带有类型信息的第 n 个元素。

我可以将结构转换为 void 指针数组,但随后我会失去我正在查看的类型的知识,同样使用联合。

整个代码库都在 c++20 中,所以我不需要担心 c 支持。

编辑:我想要这个用于以下用途。我将创建一个可变参数宏,将任意数量的输入转换为指向 then 的指针数组。这将传递给处理函数,该函数将根据命令字符串以任意顺序处理它们。例如“返回 $var1 + $var2”。处理需要随机访问元素一次或多次,因此“索引”一个结构。然而,为了支持算术,需要知道类型。

回答

是的,这是可以做到的。有些代码编写起来有点棘手,但Boost PFR已经完成了繁重的工作,因此您可以执行以下操作:

ptrs p;

float * f = boost::pfr::get<3>(p); // get the `float *` member
*f = 123.4f;                       // and write via the pointer

[请注意,我只将其分成两行,所以我可以对每个步骤进行评论——这样的事情也*boost::pfr::get<3>(p) = 123.4f;应该没问题。]

对于任何关心的人来说,如何做到这一点的基本思想相当简单——只是细节变得棘手。

基本方法是使用结构化绑定来获取您关心的项目。棘手来自几个方面:您不知道您正在处理什么类型,并且类型各不相同,因此它不像创建一个项目数组并索引到该数组那样简单。

但是,简化很多,我们可以做这样的事情:

template <std::size_t index>
constexpr auto& get(auto& your_struct)
{
    auto& [zero, one, two, three] = your_struct;

    if constexpr (index == 0)
        return zero;
    if constexpr (index == 1)
        return one;
    if constexpr (index == 2)
        return two;
    return three;
}

我再说一遍:我正在简化相当多的内容(例如,我刚刚使用了固定数量的成员),但这至少是大致的总体思路——使用结构化绑定来获取成员,并使用 constexpr 条件进行选择您关心哪一个,模板参数(以 的形式auto)基本上适用于所有部分,因此您可以处理碰巧存在的任何类型。

哦,还有一个细节处理起来有点棘手:就目前而言,这种实现只能适用于一种类型。也就是说,如果您尝试使用get<0>and get<3>,您将收到关于推导返回类型不一致的错误。因此,就目前而言,您可以使用get<0> get<2>(或其他),但不能同时使用两者,因此这纯粹是概念的有限证明,而不是实际实现(根本)。

不过,这是一个有效的演示程序:

#include <cstddef>
#include <iostream>

struct ptrs {
    int* a;
    const char** b;
    int* c;
    float* d;
};

template <std::size_t index>
constexpr auto& get(auto& your_struct)
{
    auto& [zero, one, two, three] = your_struct;

    if constexpr (index == 0)
        return zero;
    if constexpr (index == 1)
        return one;
    if constexpr (index == 2)
        return two;
    return three;
}

int main() {
    ptrs p;
    p.d = new float; // `get<3>(p) = new float;` works fine too.

    *get<3>(p) = 123.4;
    
    // show we're accessing the same data either way:
    std::cout << *get<3>(p) << "t" << *(p.d) << "n";

    // type information is retained. For example, if we try to do this:
    // get<3>(p) = new int;  // <-- note int instead of float
    // g++ 10 gives the error: "cannot convert ‘int*’ to ‘float*’ in assignment"
}


以上是有没有办法访问结构的第n个元素?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>