模板类的自动类型演绎强制?

时间:2017-08-06 01:21:08

标签: c++ templates

我在模板类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;
}
  1. 如果函数接受(A_top&lt; A_storage&gt;&amp;)作为参数,我该如何创建可以转换A_top&lt; A_overlay&lt; A_storage&gt;&gt;&amp;到A_top&lt; A_storage&gt;&amp; ?
  2. 谢谢, Nachum

2 个答案:

答案 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关系。所以这显然是一个糟糕的设计!