【问题标题】:How do I duplicate Delphi's indexed properties in c++?如何在 C++ 中复制 Delphi 的索引属性?
【发布时间】:2019-01-28 14:30:49
【问题描述】:

我希望能够让 Delphi 中存在的以下构造也可以在 c++ 中工作

首先是Delphi代码:

type
  TSlice = record
  private
    function GetData4: UINT32; inline;
    procedure SetData4(Index: 0..15; Value: UINT32); inline;
  public
    Data8: array[0..7] of UINT64;
    property Data4[index: 0..15]: UINT32 read GetData4 write SetData4;
  end;

现在是我拥有和工作的 c++ 代码:

struct TSlice {
    UINT64 Data8[8];

    __device__ __forceinline__ UINT32 * Data4() { return reinterpret_cast<UINT32*>(Data8); }
}

但是,我还是要写

for (auto i = 0; i < 3; i++) {
    Slice->Data4()[lane * 4] = SliverPart;
    Slice->Data4()[lane * 4 + 1] = SliverPart;
}

我真的很想在这里删除()Slice-&gt;Data2[lane * 4]

Data4 声明为UINT32 *const Data4 = (UINT32 *)&amp;Data8;
在结构中没有帮助,因为这让我获得了额外的 8 个字节,这不是我想要的。
我希望翻译是无缝的。

我该怎么做?

我正在考虑重载 [] 运算符,但这需要使 Data4 成为一个子结构,即使这样我也不确定如果我想让所有东西都可以内联工作(即没有任何运行时)它会起作用高架)。

使用联合有效,但我需要在客户端代码中输入的点数超出了这个世界 (classname.unionname.datamember.arrayname[index])

【问题讨论】:

  • 我不认为你可以在 C++ 中得到这个。生命周期规则妨碍了。
  • 如果您使用 Embarcadero C++ Builder,那么它已经扩展了 C++ 语言以具有属性。在普通的 C++ 中没有办法做到这一点。
  • 哦,请注意您的 Data4 函数会中断 strict aliasing
  • @Someprogrammerdude,Ja,我知道,我没关系。我必须在这里偷工减料。

标签: c++ delphi properties


【解决方案1】:

当且仅当,您使用的是 C++Builder,那么您可以使用它的 __property 扩展,它直接等效于 Delphi 的 property,例如:

struct TSlice
{
private:
    UINT32 GetData4(int Index);
    void SetData4(int Index, UINT32 Value);

public:
    UINT64 Data8[8];
    __property UINT32 Data4[int Index] = {read=GetData4, write=SetData4};
};

在其他 C++ 编译器中,这直接是不可能的,但是您可以通过使用一些辅助代理来获得 close:例如:

struct TSlice
{
private:
    UINT32 GetData4(int Index);
    void SetData4(int Index, UINT32 Value);

public:
    UINT64 Data8[8];

    TSlice() : Data4(*this) {}

    struct proxy
    {
    private:
        TSlice &m_slice;
        int m_index;

    public:
        proxy(TSlice &slice, int index) : m_slice(slice), m_index(index) {}

        operator UINT32() { return m_slice.GetData4(m_index); }
        proxy& operator=(UINT32 value) { m_slice.SetData4(m_index, value); return *this; }
    };

    struct property
    {
    private:
        TSlice &m_slice;

    public:
        property(TSlice &slice) : m_slice(slice) {}
        proxy operator[](int Index) { return proxy(m_slice, index); }
    };

    property Data4;
};

或者,您可以只使用匿名联合:

struct TSlice 
{
    union {
        UINT64 Data8[8];
        UINT32 Data4[16];
    };
};

【讨论】:

  • 匿名联合适用于读/写属性,是最干净的选项。它还允许作为const 传递的类访问其Datax 成员。我还没有尝试过代理,是否允许将TSlice 作为 const 参数传递并访问Data4[]
  • @Johan 在这种情况下,property 需要一个 const operator[] 来返回一个只读的proxy,它没有实现operator=。此外,GetData4() 也需要声明为 const
【解决方案2】:

C++ 中没有这样的功能。

我正在考虑重载 [] 运算符,但这需要使 Data4 成为子结构 [...]

但我认为这实际上是您可以获得最接近预期结果的方法。也许一个简单的std::array 已经提供了您所需要的一切?

class WhatEver
{
public:
    std::array<int, 7> property;
};

WhatEver w;
w.property[0];
for(auto& p : w.property) { /* ... */ }

如果您需要更细粒度的访问控制或std::array(甚至std::vector)证明无法解决您的需求,一些适当的包装类可能会这样做:

class Outer
{
public:
    class Inner
    {
    public:
        [...]& operator[](size_t index);
        [...] begin(); // to allow range based for loop
        [...] end();
        // and const versions of
    private:
        friend class Outer; // so that outer can use the internals
        Inner(); // constructors as needed, destructor, ...
        // data container(s) as needed
    };
    Inner property;
};

用法保持不变,嵌套类可能会使用其内部容器的数据类型,并在其自己的函数中转发给后者的函数。

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 2011-01-30
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2020-08-05
    • 1970-01-01
    相关资源
    最近更新 更多