我在模板类I' m中有2个问题。我在下面列出了示例代码。第一个问题是我是否可以强制为模板类扣除自动类型。即:
自动p = myvar;
其中myvar是T< ...>,我可以强制自动检测Q< ...>?这是简化的。请继续阅读以获得更清晰的解释。
为清晰起见编辑:让我解释一下我在做什么。而且我还想表明这个样式代码正在大规模地完成一个大型项目。我试图添加一些功能和功能,以及消除一些更尴尬的行为。
代码使用模板来执行n维数组的工作。该模板有一个顶级类,下面有一个存储类。将存储类传递到顶级类允许继承存储类的顶级类。所以我从NDimVar开始,我有NDimStor。我最终得到了
NDimVar<NDimStor>
除了数据缓冲区外,该类包含NO DATA:
class NDimStor<size_t... dimensions> {
int buffer[Size<dimensions...>()]
}
这使得类的地址==缓冲区的地址。这是整个实施的关键。这是一个不正确的假设吗? (我可以看到这在我的系统上运行没有任何问题,但也许情况并非如此。)
当我创建NDimVar&lt; NDimStor&lt; 10,10&gt;&gt;我最终得到了一个10x10阵列。
我有获取数组片段的函数,例如:
NDimVar<NDimStor<dimensions...>>::RemoveDim & get(int index);
这将在2d 10x10阵列中创建一个包含10个元素的新1d数组:
NDimVar<NdimStor<10>>
为了将此作为参考返回,我在所需数据的位置使用reinterpret_cast。所以在这个例子中,get(3)将执行:
return reinterpret_cast<NDimVar≤NDimStor<dimensions...>>::RemoveDim&>(buffer[index * DimensionSumBelow<0>()]);
DimensionSumBelow&℃,GT;返回维度1+的元素总和,即10.因此&amp; buffer [30]是引用的1d NDimVar的地址。
所有这些都很有效。
我唯一的问题是我想添加叠加层。例如,能够返回对新类的引用:
NDimVar<NDimPermute<NDimStor<10,10>,1,0>>
指向相同的原始位置以及置换行为(交换维度)。这也很有效。但我想:
auto p = myvar.Permute<1,0>()
使用置换数据创建myvar的新副本。如果我说:
,这将有用NDimVar<NDimStor<10,10>> p = myvar.Permute<1,0>().
我觉得有一些自动类型演绎的东西我可以做,以强制返回的自动类型,但我不确定。我还没有弄明白。
再次感谢, Nachum
我想要的是: 1.在我的存储上创建临时覆盖类,例如A_top&LT; A_storage&GT;可以返回名为A_top&lt; A_overlay&lt; A_storage&gt;&gt;的类型在不创建新对象的情况下,它只返回对此类型的引用。这会更改存储的访问方式。问题在于调用auto。我不希望直接实例化此类型。我可以将返回自动修改为原始A_top吗?
#include <iostream>
using namespace std;
class A_storage {
public:
float arr[10];
A_storage () {
}
float & el (int index) {
return arr[index];
}
};
template <typename T> class A_overlay : T {
private:
A_overlay () {
cout << "A_overlay ()" << endl;
}
A_overlay (const A_overlay &) {
cout << "A_overlay (&)" << endl;
}
public:
using T::arr;
float & el (int index) {
return arr[10 - index];
}
};
template <typename T> class A_top;
template <typename T> class A_top : public T {
public:
A_top () {
}
A_top<A_overlay<A_storage>> & get () {
return reinterpret_cast<A_top<A_overlay<A_storage>>&>(*this);
}
};
using A = A_top<A_storage>;
int main (void) {
A a;
auto c = a.get(); // illegal - can i auto type deduce to A_top<A_storage>?
return 0;
}
谢谢, Nachum
答案 0 :(得分:1)
首先,你的设计看起来不对我,我不确定这种行为是否真的定义得很好。 (可能不是。)
无论如何,问题不在auto
。该错误是由A_overlay
的复制构造函数是私有的,而您需要它将A_top<A_overlay<A_storage>>
返回的a.get()
复制到auto c
。
(请注意,在这种情况下,auto
显然会被推断为A_top<A_overlay<A_storage>>
,我假设您在说A_top<A_storage>
时发了错字。)
另请注意,A_storage
中的A_top::get()
应替换为T
,即使它不会更改您的代码段中的任何内容,因为您只有T == A_storage
。
嗯,不仅仅是这个:如果函数接受(A_top&amp;)作为参数,我该如何创建可以转换A_top&gt;的转换函数?到A_top&amp; ?
return reinterpret_cast<A_top<A_storage>&>(obj);
答案 1 :(得分:0)
reinterpret_cast
。它实质上删除了与类型相关的任何编译器验证。并且执行不相关的转换本质上是未定义的行为,因为它基本上假设派生类总是在偏移0 ...
编写此类代码没有任何意义。它无法维护且难以理解您要实现的目标。看起来您想假装您的A_top<A_storage>
对象是A_top<A_overlay<A_storage>>
对象。 如果这是您要执行的操作,请将A
别名声明为该类型。
在您的代码中,您似乎想要反转索引,以便在您询问位置0处的项目时返回位置10处的项目,反之亦然。 您是否真的认为,从您的混淆代码中可以看出这一点?从不编写这么糟糕的代码。
像
这样的东西class A_overlay {
public:
float & el (int index) { return arr[10 - index]; }
private:
A_storage arr;
};
比你当前的代码更有意义。
显然,您会根据需要更新以下行:
using A = A_top<A_storage>;
此外,如果A_top
没有用处,那么为什么不直接使用A_overlay
?如果A_storage
不是模板,为什么要使用模板?你真的想在你的代码库中的其他地方重用这些混乱。
显然,如果您编写此类代码,您的代码继承不会尊重IS-A关系。所以这显然是一个糟糕的设计!