Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;强制转换为较小大小的数组 这是一个有趣的问题,关于C++语言的各种怪癖。我有一对函数,它们应该用矩形的角填充点数组。它有两个重载:一个取点[5],另一个取点[4]。5点版本指的是闭合多边形,而4点版本指的是只需要4个角的时间段_C++_Arrays_Reinterpret Cast - Fatal编程技术网

C++;强制转换为较小大小的数组 这是一个有趣的问题,关于C++语言的各种怪癖。我有一对函数,它们应该用矩形的角填充点数组。它有两个重载:一个取点[5],另一个取点[4]。5点版本指的是闭合多边形,而4点版本指的是只需要4个角的时间段

C++;强制转换为较小大小的数组 这是一个有趣的问题,关于C++语言的各种怪癖。我有一对函数,它们应该用矩形的角填充点数组。它有两个重载:一个取点[5],另一个取点[4]。5点版本指的是闭合多边形,而4点版本指的是只需要4个角的时间段,c++,arrays,reinterpret-cast,C++,Arrays,Reinterpret Cast,显然,这里有一些重复的工作,所以我希望能够使用4点版本来填充5点版本的前4点,所以我不会重复代码。(并不是说复制太多,但每当我复制和粘贴代码时,我都会有严重的过敏反应,我希望避免这种情况。) P> >,C++似乎并不关心将 T[M] < /代码>转换成 t[n] < />代码>代码> nstatic_cast似乎认为这些类型出于某种原因不兼容重新解释施法当然处理得很好,但它是一种危险的动物,一般来说,最好尽可能避免 所以我的问题是:在数组类型相同的情况下,是否有一种类型安全的方法将一个大小的数组

显然,这里有一些重复的工作,所以我希望能够使用4点版本来填充5点版本的前4点,所以我不会重复代码。(并不是说复制太多,但每当我复制和粘贴代码时,我都会有严重的过敏反应,我希望避免这种情况。)

P> >,C++似乎并不关心将<代码> T[M] < /代码>转换成<代码> t[n] < />代码>代码> ncode>static_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;
}
void RectToPointArray(常量和矩形、degPoint和points)[4])
{
点[0]。lat=rect.nw.lat;点[0]。lon=rect.nw.lon;
点[1]。lat=rect.nw.lat;点[1]。lon=rect.se.lon;
点[2]。lat=rect.se.lat;点[2]。lon=rect.se.lon;
点[3]。lat=rect.se.lat;点[3]。lon=rect.nw.lon;
}
void RectToPointArray(常量和矩形、degPoint和points)[5])
{
//如果可能,我想在这里使用更安全的类型检查:
RectToPointArray(rect,重新解释铸造(点));
点[4]。lat=rect.nw.lat;点[4]。lon=rect.nw.lon;
}

[Edit2]通过引用传递数组的意义在于,我们至少可以模糊地确定调用方传递的是正确的“输出参数”。

我认为通过重载来实现这一点不是一个好主意。函数名不会告诉调用方它是否要填充打开的数组。如果调用者只有一个指针,并且想要填充坐标(假设他想要填充多个矩形,以不同的偏移量作为更大数组的一部分),该怎么办

我将通过两个函数来实现这一点,并让它们获取指针。大小不是指针类型的一部分

void fillOpenRect(degRect const& rect, degPoint *p) { 
  ... 
}

void fillClosedRect(degRect const& rect, degPoint *p) { 
  fillOpenRect(rect, p); p[4] = p[0]; 
}
我看不出这有什么不对。您的重新解释转换在实践中应该可以很好地工作(我不认为会出现什么错误-对齐和表示都是正确的,因此我认为仅仅形式上的不确定性在这里不会实现),但是正如我上面所说的,我认为没有充分的理由让这些函数通过引用来获取数组


如果您想要一般地执行它,您可以通过输出迭代器来编写它

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;
}
模板
输出迭代器fillOpenRect(degRect const&rect,输出迭代器out){
typedef typename迭代器_traits::value_type value_type;
值\u类型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}
};
对于(int i=0;i<4;i++)
*out++=pt[i];
返回;
}
模板
输出迭代器fillClosedRect(递减常量和矩形,输出迭代器输出){
typedef typename迭代器_traits::value_type value_type;
out=fillOpenRect(rect,out);
值_type p1={rect.nw.lat,rect.nw.lon};
*out++=p1;
返回;
}
然后,您可以将其用于向量和数组,无论您最喜欢什么

std::vector<degPoint> points;
fillClosedRect(someRect, std::back_inserter(points));

degPoint points[5];
fillClosedRect(someRect, points);
std::向量点;
fillClosedRect(sometrect,std::back_inserter(点));
degPoint点[5];
fillClosedRect(某些直线,点);

如果您想编写更安全的代码,可以使用向量方式和反向插入器,如果您使用较低级别的代码,则可以使用指针作为输出迭代器

我会使用
std::vector
或者(这非常糟糕,不应该使用)在某些极端情况下,您甚至可以通过
Point*
之类的指针使用普通数组,这样您就不应该有这样的“铸造”问题。

为什么不传递一个标准指针,而不是像这样大小的指针呢

void RectToPointArray(const degRect& rect, degPoint * points ) ;

我想您可以使用函数模板专门化,如下所示(第一个参数被忽略,函数名被f()替换的简化示例):

#包括
使用名称空间std;
X类
{
};
模板
国际货币基金组织(X&X)[sz])
{

cout我不认为你对这个问题的框架/想法是正确的。你通常不需要具体地键入一个有4个顶点的对象和一个有5个顶点的对象

但如果必须键入,则可以使用
struct
s来具体定义类型

struct Coord
{
    float lat, long ;
} ;
然后

那么

然而,我认为这个解决方案有点极端,使用
assert
s检查其大小(4或5)的
std::vector也可以

所以我的问题是:有没有 类型安全的方法来强制执行 将一个大小转换为较小大小的数组 其中数组类型相同

不,我认为语言根本不允许你这样做:考虑将int(10)铸造到int(5)。但是,你总是可以得到一个指针,但是我们不能“欺骗”编译器,认为一个固定大小的维度有不同的数量。

如果您不打算使用STD::向量或其他容器,它可以正确地识别运行时内部点的数量,并且在一个函数中方便地完成这两个函数,而不是基于元素的数量来调用两个函数重载,而不是试图进行疯狂的转换,那么至少考虑这是一个改进:

void RectToPointArray(const degRect& rect, degPoint* points, unsigned int size);
如果你是
struct Rectangle
{
    Coord points[ 4 ] ;
} ;

struct Pentagon
{
    Coord points[ 5 ] ;
} ;
// 4 pt version
void RectToPointArray(const degRect& rect, const Rectangle& rectangle ) ;

// 5 pt version
void RectToPointArray(const degRect& rect, const Pentagon& pent ) ;
void RectToPointArray(const degRect& rect, degPoint* points, unsigned int size);
template <class T, size_t N>
std::size_t array_size(const T(&/*array*/)[N])
{
    return N;
}
template <size_t N>
void RectToPointArray(const degRect& rect, degPoint(&points)[N])
{
    assert(N >= 4 && "points requires at least 4 elements!");
    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;

    if (N >= 5)
        points[4].lat = rect.nw.lat; points[4].lon = rect.nw.lon;
}