防止C样式阵列指针的升级

Preventing upcasts for C style array pointers

本文关键字:指针 阵列 样式 防止      更新时间:2023-10-16
struct Entry
{
    int Data0;
};
struct ExtendedEntry : public Entry
{
    int Data1;
};

我有一种简单的方法,可以期待C-Style数组指向进入这样的条目

void Calculate(Entry* data, int count);

将指针传递到一系列扩展程序时,这种方法显然会失败。如何防止用户这样做?

ExtendedEntry items[50];
// [...]
Calculate(items, 50);

不是我追求防弹的API,我只想防止我和我的同事再次犯同样的错误。

制作一个简单的包装器:

template <typename TEntry>
void CalculateSafe(TEntry* data, int count)
{
    static_assert(sizeof(TEntry) == sizeof(Entry), "size mismatch");
    Calculate(data, count);
}

,只要它具有相同的尺寸,就可以通过任何派生类型,这将解决您在CAPI需要在数组中进行指针算术时所面临的问题。

@john zwinck的解决方案非常好!

然而,还有另一种方法。您可以定义这样的方法:

template < class T >
void Calculate(T * arr, int count)
{
    static_assert(std::is_base_of<Entry, T>::value, "true");
    for (int i = 0; i < count; i++)
        std::cout << arr[i].Data0 << std::endl;
}

虽然模板确保实现的正确性,但static_assert保证您仅使用预定义的类型调用此方法。

,或者您可以声明已删除的过载:

template<class T,std::size_t N>
std::enable_if_t<!std::is_same_v<T,Entry>> 
Calculate(const T(&)[N],int)
  = delete;

您也可以通过类型大小比较替换类型的比较。