要聚合的结构必须知道聚合此结构的结构中的信息

The structure being aggregated has to know the information from the structure that aggregates this structure

本文关键字:结构 信息      更新时间:2023-10-16

就像在std::p air<int,std::vector>向量必须知道它是对的第一个元素(即int)。

我遇到了以下有趣的问题。提供代码,请阅读评论。

#include <vector>
#include <string>
#include <iostream>
namespace DataWorld {
    using DataType = int;
    // It is a data. Holder struct will hold this data. But holder has it's id
    struct Data {
        DataType storage[5];
        void Show() {
            std::cout << "my_holder_index" << " "; // here the data has to know the id of the holder that holds this data
            for(auto elem : storage) {
                std::cout << elem << " ";
            }
            std::cout << std::endl;
        }
    };
    struct DataHolder {
        Data my_data;
        std::string my_holder_index;
        DataHolder(Data my_data, std::string my_holder_index)
            : my_data(my_data)
            , my_holder_index(my_holder_index) {}
        void Show() {
            // Do not show holder id here! It is the data that has to know it.
            my_data.Show();
        }
    };
}
int main() {
    using namespace DataWorld;
    DataHolder dhs[] = {
        { {1, 2, 3, 4, 5}, "nat" },
        { {1, 3, 5, 7, 9}, "even" },
        { {2, 4, 6, 8, 10}, "odd" }
    };
    for(auto dh : dhs) {
        dh.Show();
    }
}
  • 无需手动向数据提供"my_holder_index"变量即可解决此任务(如": my_data(my_data(my_holder_index))")。

  • std::vector 是否可以在内存中找到实例化其 DataHolder 结构的位置并尝试查找my_holder_index?

  • 是否可以在没有点内存操作的情况下使用 c++/STL 实现此行为?谢谢

由于您尚未解释您的问题中的任何内容与vector有什么关系(以及荒谬地声称pair中的vector可以访问pair中的其他元素),我将专注于为您呈现的实际代码找到解决方案。

问题2:

std::vector 是否有可能在内存中找到实例化其 DataHolder 结构的位置并尝试查找my_holder_index?

不。在C++(即:不调用 UB)中,成员子对象没有合法的方式来访问在其拥有对象中声明的变量。至少,如果没有您将该变量传递给它,则不会。

哦,当然,您可能可以将this转换为unsigned char*,进行一些指针算术,然后将其转换为std::string。这可能对某些实现"有效"。但这不会是合法的C++。如果没有其他原因,只是没有什么能阻止您在不在提供std::string成员的其他对象内的位置声明Data

问题1和3:

无需手动向数据提供"my_holder_index"变量即可解决此任务(如": my_data(my_data(my_holder_index))")。

是否可以在没有点内存操作的情况下使用 c++/STL 实现此行为?

执行

您正在执行的操作的正确方法是使用 CRTP。 Data应该是 DataHolder 的基类子对象(或其他任何人可能想要使用它)。它将采用将从它派生的类作为模板参数。因此,它可以static_cast this指向派生类的指针。只要始终将派生类作为模板参数传递,就不会引发未定义的行为:

template<typename Derived>
  //Requires that `Derived` have a publicly accessible `my_holder_index` field
  //Which is something that has an `operator<<(ostream)` overload for it.
struct Data {
    DataType storage[5];
    void Show() {
        std::cout << "my_holder_index" << derived().my_holder_index;
        for(auto elem : storage) {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
private:
    Derived &derived() {return static_cast<Derived&>(*this);}
    const Derived &derived() const {return static_cast<const Derived&>(*this);}
};
struct DataHolder : Data<DataHolder> {
    std::string my_holder_index;
    DataHolder(std::string my_holder_index)
        : my_holder_index(my_holder_index) {}
    void Show() {
        // Do not show holder id here! It is the data that has to know it.
        Data<DataHolder>::Show();
    }
};