用于递归模板评估的转换数组类型

时间:2015-12-30 23:34:17

标签: c++ arrays templates

我本来希望包含一个最小的例子,但由于我的问题的性质,我不能提供一个。

我将我的问题减少到无法对数组进行类型转换。这是一个代码片段,显示了我想写的内容:

template <size_t N>
size_t arrLen(int(&data)[N])
{
    return N;
}

int main(int argc, char** argv)
{
    int arr[] = { 1, 2, 3, 4, 5, 6 };

    size_t working = arrLen(arr);

    int * p = &arr[1];
    size_t len = 3;

    size_t len_is_not_a_constant_value = arrLen(*(int(*)[len])p);
}

我的游乐场算法是在一维阵列中找到任何峰值,其中峰值被定义为大于或等于峰值邻居。算法本身对我来说并不重要。下面的代码已经注释掉了我想要包含但不能编译的行,因为它不会编译。没有那些行,算法是不正确的。

template <size_t N>
int getpeak1D_templated(int(&data)[N])
{
    size_t offset = N / 2;

    if (data[offset] < data[offset - 1])
    {
        int * p = data;
        size_t len = offset;
        //return getpeak1D_templated(*(int(*)[len])p);
        return 0;
    }
    else if (data[offset] < data[offset + 1])
    {
        int * p = &data[offset];
        size_t len = N - offset;
        //return offset + getpeak1D_templated(*(int(*)[len])p);
        return 0;
    }
    else
    {
        return offset;
    }
}

int getpeak1D_templated(int(&data)[1])
{
    return 0;
}

int getpeak1D_templated(int(&data)[2])
{
    if(data[0] < data[1]) return 1;
    return 0;
}

这是未模板化的版本。这将编译并且应该是正确的。

int getpeak1D(int * data, size_t N)
{
    size_t offset = N / 2;

    size_t offset_m1 = offset - 1;
    size_t offset_p1 = offset + 1;

    if (N >= offset_m1 && data[offset] < data[offset_m1])
    {
        return getpeak1D(data, offset);
    }
    else if (N >= offset_p1 && data[offset] < data[offset_p1])
    {
        return offset + getpeak1D(data + offset, N - offset);
    }
    else
    {
        return offset;
    }
}

我可以看到为什么*(int(*)[len])p无效。

感觉有些东西我不知道了。这个递归终止,我将能够手动编写所有特化(对于合理的起始数组大小)。我假设我在这里做错了。不知何故,这种递归应该可以使用模板。

是否有我丢失的数组转换版本?

我错过了一些完全不同的东西吗?

编辑: 我实际上可以看看为什么这是无效的。我的观点是N是常量,并且所有操作都定义得很好,以至于它们可以在编译时解析。因此,对于大小为N的数组,递归的所有分支都可以展开。我正在寻找一种到达那里的方法。演员表是不正确的,永远不会是正确的。

3 个答案:

答案 0 :(得分:1)

错误应该很清楚。例如,len不是编译时常量,并且您不能拥有可变长度数组(或者转换为指向它的指针)。其次,arrLen如何在编译时实例化,而不知道len是什么?

使用非模板版本。

答案 1 :(得分:1)

如果start.sh不是编译时常量积分表达式,则无法实现此目的。它也没什么意义.¹

你真的需要通过len或类似的。请参阅CppCoreGuidelines:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-array

¹邪恶扭曲的解决方法

您可以随时启用array_view并进行强制转换:

len

答案 2 :(得分:1)

你不能只用N / 2和N-N / 2替换注释行中的len。 像这样:

template <size_t N>
int getpeak1D_templated(int(&data)[N])
{
    size_t ret = 0;
    size_t offset = N / 2;
    if (data[offset] < data[offset - 1])
    {
        int * p = data;
        ret = getpeak1D_templated(*(int(*)[N/2])p);
    }
    else if (data[offset] < data[offset + 1])
    {
        int * p = &data[offset];
        ret =  offset + getpeak1D_templated(*(int(*)[N - N/2])p);
    }
    else
    {
        ret =  offset;
    }
    return ret;
}

int getpeak1D_templated(int(&data)[1])
{
    return 0;
}

int getpeak1D_templated(int(&data)[2])
{
    if(data[0] < data[1]) return 1;
    return 0;
}