Sea*_*rds 8 c++ arrays reinterpret-cast
这是一个关于C++语言各种怪癖的有趣问题.我有一对函数,它们应该用矩形的角填充一系列点.它有两个重载:一个需要a Point[5],另一个需要a Point[4].5点版本是指一个封闭的多边形,而4点版本是指你只想要4个角落的周期.
显然这里有一些重复的工作,所以我希望能够使用4点版本填充5点版本的前4个点,所以我不会复制该代码.(并不是说复制很多,但每当我复制和粘贴代码时,我都会有可怕的过敏反应,我想避免这种情况.)
问题是,C++似乎并不关心将a转换T[m]为T[n]where 的想法n < m.static_cast似乎认为这些类型由于某种原因是不相容的.reinterpret_cast当然,处理它很好,但是作为一般规则,如果可能的话,最好避免它.
所以我的问题是:是否有一种类型安全的方法将一个大小的数组转换为一个较小的数组,其中数组类型是相同的?
[编辑]代码,是的.我应该提到参数实际上是对数组的引用,而不仅仅是指针,因此编译器知道类型的区别.
void RectToPointArray(const degRect& rect, degPoint(&points)[4])
{
points[0].lat = rect.nw.lat; points[0].lon = rect.nw.lon;
points[1].lat = rect.nw.lat; points[1].lon = rect.se.lon;
points[2].lat = rect.se.lat; points[2].lon = rect.se.lon;
points[3].lat = rect.se.lat; points[3].lon = rect.nw.lon;
}
void RectToPointArray(const degRect& rect, degPoint(&points)[5])
{
// I would like to use a more type-safe check here if possible:
RectToPointArray(rect, reinterpret_cast<degPoint(&)[4]> (points));
points[4].lat = rect.nw.lat; points[4].lon = rect.nw.lon;
}
Run Code Online (Sandbox Code Playgroud)
[Edit2]传递一个数组的引用点是为了让我们至少可以模糊地确定调用者正在传递一个正确的"out参数".
我认为通过重载来做到这一点不是一个好主意。函数的名称不会告诉调用者它是否要填充一个开放数组。如果调用者只有一个指针并且想要填充坐标(假设他想要填充多个矩形以成为不同偏移量的更大数组的一部分)怎么办?
我会通过两个函数来做到这一点,并让它们接受指针。大小不是指针类型的一部分
void fillOpenRect(degRect const& rect, degPoint *p) {
...
}
void fillClosedRect(degRect const& rect, degPoint *p) {
fillOpenRect(rect, p); p[4] = p[0];
}
Run Code Online (Sandbox Code Playgroud)
我不明白这有什么问题。您的重新解释转换在实践中应该可以正常工作(我不知道会出现什么问题 - 对齐和表示都是正确的,所以我认为在这里仅仅形式上的不确定性不会落实到现实中),但正如我所说的上面我认为没有充分的理由让这些函数通过引用来获取数组。
如果要通用的话,可以通过输出迭代器来写
template<typename OutputIterator>
OutputIterator fillOpenRect(degRect const& rect, OutputIterator out) {
typedef typename iterator_traits<OutputIterator>::value_type value_type;
value_type pt[] = {
{ rect.nw.lat, rect.nw.lon },
{ rect.nw.lat, rect.se.lon },
{ rect.se.lat, rect.se.lon },
{ rect.se.lat, rect.nw.lon }
};
for(int i = 0; i < 4; i++)
*out++ = pt[i];
return out;
}
template<typename OutputIterator>
OutputIterator fillClosedRect(degRect const& rect, OutputIterator out) {
typedef typename iterator_traits<OutputIterator>::value_type value_type;
out = fillOpenRect(rect, out);
value_type p1 = { rect.nw.lat, rect.nw.lon };
*out++ = p1;
return out;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将它与向量一起使用,也可以与数组一起使用,无论您最喜欢什么。
std::vector<degPoint> points;
fillClosedRect(someRect, std::back_inserter(points));
degPoint points[5];
fillClosedRect(someRect, points);
Run Code Online (Sandbox Code Playgroud)
如果您想编写更安全的代码,您可以使用带有后向插入器的向量方式,如果您使用较低级别的代码,您可以使用指针作为输出迭代器。