防止C风格数组指针的upcast

时间:2017-09-28 12:45:21

标签: c++ casting

struct Entry
{
    int Data0;
};

struct ExtendedEntry : public Entry
{
    int Data1;
};

我有一个简单的方法,期望像这样的

的C样式数组指针
void Calculate(Entry* data, int count);

当将指针传递给ExtendedEntrys数组时,此方法显然失败。如何防止用户这样做?

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

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

3 个答案:

答案 0 :(得分:7)

制作一个简单的包装器:

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

只要它具有相同的大小,就可以传递任何派生类型,这将解决当C API需要在数组中进行指针运算时所遇到的问题。

答案 1 :(得分:2)

@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确保您只使用预定义的类型调用此方法。

答案 2 :(得分:0)

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

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

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