2017-08-06 61 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