2017-08-06 64 views
-3

我在创建模板类时遇到了2个问题。我已经在下面包含了示例代码。第一个问题是我是否可以强制为模板类别扣除自动类型。即:模板类的汽车类演绎强制?

auto p = myvar;

其中myvar是T < ...>,我可以强制自动检测Q < ...>?这是简化的。请继续阅读以获得更清晰的解释。

为清楚起见进行了编辑:让我解释我在做什么。而且我还想指出,这种风格代码非常适用于大型项目。我试图添加一些功能和功能,并且除了消除一些更尴尬的行为。

该代码使用模板在n维数组上执行工作。该模板有一个顶层类,下面有一个存储类。将存储类传递到顶级类允许继承存储类的顶级类。所以我从NDimVar开始,我有NDimStor。我最终

NDimVar<NDimStor> 

类不包含任何数据,除了数据的缓冲器:

class NDimStor<size_t... dimensions> { 
int buffer[Size<dimensions...>()] 
} 

这使得类==缓冲器的地址的地址。这是整个实施的关键。这是不正确的假设吗? (我可以看到这个作品在我的系统上没有任何问题,但也许这并非总是如此。)

当我创建NDimVar < NDimStor < 10,10 > >我结束了一个10×10阵列。

我有功能,让该阵列的片,例如:

NDimVar<NDimStor<dimensions...>>::RemoveDim & get(int index); 

这产生10种元素的一个新的一维数组出2D 10×10阵列的:

NDimVar<NdimStor<10>> 

为了返回这个作为参考,我在我想要的数据位置使用reinterpret_cast。因此,在这个例子中,得到(3)将进行:

return reinterpret_cast<NDimVar≤NDimStor<dimensions...>>::RemoveDim&>(buffer[index * DimensionSumBelow<0>()]); 

DimensionSumBelow < 0>返回在尺寸元素的总和1+,即10.所以&缓冲器[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 <A_storage>可以返回一个类型,称为A_top < A_overlay <A_storage> >而不创建新对象,它只是返回对此类型的引用。这改变了存储访问的方式。问题出在自动调用。我不希望这个类型被直接实例化。我可以修改返回到自动作为原始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; 
} 
  • 如果函数接受(A_top <A_storage> &)作为参数,如何可以创建一个转换功能,可以投A_top < A_overlay <A_storage> > &到A_top <A_storage> &?
  • 感谢, Nachum

    +2

    如果汽车让你感到困惑,那就从不使用它开始吧。放入你想要的类型,让编译器告诉你是否有错误。不过,由于缺乏对C++基本部分的理解,你所做的事情可能太复杂。我建议从简单的事情开始。你似乎有多层混乱,这将使你难以理解你的具体问题的任何答案 - 也使你的问题难以回答,因为它有点荒谬。 – xaxxon

    回答

    1

    首先,你的设计不看我的权利,我不知道,如果行为实际上是明确与否。 (可能不是)

    在任何情况下,问题都不在auto。错误是由于A_overlay的拷贝构造函数是私有的,而您需要拷贝由a.get()返回的A_top<A_overlay<A_storage>>auto c

    (注意,在这种情况下,auto显然被推断为A_top<A_overlay<A_storage>>,我认为当说,这是A_top<A_storage>输入有误。)


    还要注意的是A_storageA_top::get()T更换,即使它没有改变你的代码片段中的任何内容,因为你只有T == A_storage


    如果函数接受(A_top &)作为参数,我怎样才能建立转换功能,可以投A_top>到A_top &?

    埃姆,不只是这一点:

    return reinterpret_cast<A_top<A_storage>&>(obj); 
    
    +1

    @nachum这对我没有意义。你可以让'get()'返回'A_top ',但是'get()'有什么意义呢? – HolyBlackCat

    +0

    代码正确。我想要覆盖版本返回。但我不想在分配时创建A_overlay。这就是为什么它有一个私人拷贝构造函数。这是故意的。我希望自动返回A_top 即使get()返回A_top >的引用。有什么办法来操纵自动类型检测来获得这种行为? - – nachum

    +0

    @nachum但他们不可兑换。即使'A_top c = a.get()'也不行。看起来你需要使用多态。 – HolyBlackCat

    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; 
    }; 
    

    将使比你当前的代码更有意义。

    • 无需演员。
    • 容易理解。
    • 明确定义的行为。
    • 你可能会保留你的工作。为什么不直接使用A_overlay

      using A = A_top<A_storage>; 
      

      而且,如果A_top有没有用处,那么:

    而且很明显,你会更新以下行是否合适?如果A_storage不是模板,为什么使用模板?你真的想在代码库的其他地方重复使用这种混乱吗?

    显然,如果您编写这样的代码,您的代码继承不尊重IS-A关系。所以这显然是一个糟糕的设计!

    +0

    请参阅我上面添加的描述。叠加层被动态地添加以允许置换排列或置换类的部分片段。所以我不能混淆所有可能创建的模板。我的例子太简单了,对不起!看看问题现在是否更清晰。任何和所有的建议表示赞赏。谢谢! – nachum

    +0

    返回代理,而不是假装您的数据是另一种类型。据我所知,通过假定数据具有给定的布局,您依赖未定义的行为。如果添加了虚拟函数或使用多重继承,这可能很容易中断... – Phil1970

    +0

    但代理是一个新类,我希望将我的数据作为参考引用。为用户保留最简单的C++语义。另外,派生类应该可以正常工作。是什么让你觉得它不会? – nachum