访问基类型数组成员(Int-to-type习惯用法)

Access base type array members (Int-to-Type idiom)

本文关键字:Int-to-type 习惯 惯用法 组成员 基类 类型 数组 访问      更新时间:2023-10-16

在试图实现Int-to-Type习惯用法时,我在继承的类中遇到了一个问题,即使在尝试了其他帖子中的几个类似解决方案后,我也无法解决这个问题。我试图在继承类中的数组上实现一个简单的排序算法。首先,我将int设置为类型enum和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 << "NOOPn";
}
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_SORTn";
}
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数组索引中的值存储在与提供给数组的类型匹配的临时变量中?

让我举一个例子。。。

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对象的内存位置取消引用它(您只有一个对象,而不是对象数组)。实际上,您的访问是越界的,并且您的代码具有未定义的行为。

错误消息实际上解释了错误:

=无法从Array转换为T

因为这里是

temp = this[j];

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

此外,在该存储器位置处不存在Array<int,49>。事实上,你很幸运地遇到了编译器错误,通常未定义的行为更为隐蔽,隐藏在看似无辜的警告后面,甚至更糟的是没有警告,而实际上没有警告时,它似乎起作用了。

根据@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--;
}
}
}