访问基本类型数组成员(Int-to-Type惯用语)

时间:2019-01-21 21:33:22

标签: c++ arrays templates

尝试实现Int-to-Type习惯用法,我在继承的类中遇到了一个问题,即使尝试了此处其他文章中的几种类似解决方案,我也无法解决。我正在尝试在继承的类中的数组上实现简单的排序算法。首先,我设置int-to-type枚举和struct:

enum class Technique : int
{
    NOOP,
    INSERTION_SORT,
    QUICK_SORT
};
template <Technique I>
struct AutoTechnique
{
    enum { value = I };
};

接下来,我使用一些工具定义从std :: array继承的Array类,该工具可根据集合的大小来处理不同的排序技术:

template <typename T, unsigned N>
class Array : public std::array<T, N>
{
    static const Technique technique = (N == 0 || N == 1) ? Technique::NOOP :
        (N < 50) ? Technique::INSERTION_SORT : Technique::QUICK_SORT;

    void sort(AutoTechnique<Technique::NOOP>)
    {
        std::cout << "NOOP\n";
    }
    void sort(AutoTechnique<Technique::INSERTION_SORT>)
    {
        int i, j;
        T temp;
        for (i = 1; i < N; i++)
        {
            j = i;
            while (j > 0 && this[j - 1] > this[j])
            {
                temp = this[j]; // Wants to assign Array<T,N> to temp, rather than value at index.
                this[j] = this[j - 1];
                this[j - 1] = temp;
                j--;
            }
        }
    }
    void sort(AutoTechnique<Technique::QUICK_SORT>)
    {
        std::cout << "QUICK_SORT\n";
    }
public:
    void Sort()
    {
        sort(AutoTechnique<technique>());
    }

};

问题与注释有关,编译器告诉我"= cannot convert from Array<int,49> to T"(int,49是一个测试用例)。

我能找到的最佳答案是建议我取消引用(* this)并使用->访问值,但是上面两行代码似乎可以正常工作,但我没有这样做,尝试取消引用该对象的几种方法均无效。

似乎主要问题在于试图将this [j]中的值分配给T temp。我尝试投射(T)this[j],但收到错误消息type cast cannot convert...

如何将值存储在this数组的索引中,该索引与提供给数组的类型匹配的临时变量中?

2 个答案:

答案 0 :(得分:2)

让我举个例子...

class foo {};

int main() {
    foo* a;
    a+5;       // fine ? 
    a[3];      // fine ? 
    foo b;
    b+5;       // error: no operator found
    b[3];      // error: no operator found
}

有一些用于指针的运算符(该示例还不完整,重点只是说明它们不是对象的运算符)。它们适用于任何类型的指针。您正在将指针操作与实例操作一起使用。比较指针与比较对象不同。

此外,当a是指针时,a[b]就是*(a+b)。因此,在您的代码中它似乎可以工作,但实际上却没有。您将this视为指向对象数组的指针,然后在没有Array对象(您只有一个,而不是它们的数组)的内存位置取消引用它。实际上,您正在访问越界,并且您的代码具有未定义的行为。

错误消息实际上说明了错误所在:

  

=无法从数组转换为T

因为这里

temp = this[j];

temp当然是T,而this[j] == *(this + j)this乘以j-sizeof(Array<int,49>)倍(即将整数添加到某种类型的指针,然后取消引用该指针以获得Array<int,49>时会发生什么。这些类型没有赋值运算符,因此会出现错误。

此外,该存储位置中没有Array<int,49>。实际上,您很幸运地遇到了编译器错误,通常未定义的行为更加笨拙,隐藏在无辜的警告之下,甚至更糟的是没有警告,而实际上却没有警告。

答案 1 :(得分:0)

@NathanOliver提供的答案中的更新代码

void sort(AutoTechnique<Technique::INSERTION_SORT>)
{
    int i, j;
    T temp;
    for (i = 1; i < N; i++)
    {
        j = i;
        while (j > 0 && (*this)[j - 1] > (*this)[j])
        {
            temp = (*this)[j];
            (*this)[j] = (*this)[j - 1];
            (*this)[j - 1] = temp;
            j--;
        }
    }
}