2016-11-03 139 views
6

首先,我有這樣的事情:C++:參考/指針成員變量作爲模板參數

class Test { 
    std::vector<int> a, b; 
    void caller(...) { callee(...); } 
    void callee(...) { /* Do stuff with 'a' */ } 
} 

我想什麼是有不完全一樣callee但對於矢量b功能。要做到這一點有兩個明顯的解決方案:

  • 傳遞矢量ab作爲參數。但是,callee是一個可以進行數百次調用的遞歸函數,並且將向量作爲參數傳遞僅僅是不必要的開銷。
  • 複製功能callee並使用向量b,這將是最好的選擇,儘管事實上callee是一個相當長的功能,我會有很多重複的代碼。

出於好奇,我去尋找模板的一部分,我注意到,可用於

lvalue reference type

pointer type

pointer to member type

於是,我就這樣做:

class Test { 
    std::vector<int> a, b; 
    void caller(...) { callee<a>(...); } 
    template <std::vector<int> &x> void callee(...) { /* Do stuff with 'x' */ } 
} 

,但我得到

error: use of ‘this’ in a constant expression

有沒有什麼辦法可以通過參照還是一個指針?

順便說一句,我想要的東西可以被看作是一個功能範圍的#define

+0

「並將向量作爲參數傳遞只是不必要的開銷」我不相信當您通過引用或指針傳遞向量時,您甚至不會注意到「開銷」。 –

+0

嗯,是的。但我更願意選擇第二種解決方案,而且根本沒有任何開銷。 – gmardau

+0

如果你想限制性地使用這樣的模板,你會想'template ',並且無論你使用哪種類型,接受一個'T&' - 如果你特別需要防止它被用於說'std: :vector '然後使用'std :: enable_if'進行不匹配。 – Olipro

回答

3

陣列甚至是元組,但是對於老成員的指針不是很好?

class Test { 
    std::vector<int> a, b; 

    void caller(/*...*/) { callee<&Test::a>(/*...*/); } 

    template <std::vector<int> Test::*vec> 
    void callee(/*...*/) { /* Do stuff with `(this->*vec)` */ } 
}; 
2

只需使用一個門面:

class Test { 
    std::vector<int> a, b; 
    void caller_a(...) { callee(a); } 
    void caller_b(...) { callee(b); } 
    void callee(std::vector<int> &a_or_b, ...) { 
    } 
} 

callee()將把它的參數,將被傳遞作爲一個或其他班級成員。

+0

這就是我在第一個項目符號解決方案中提到的內容。 – gmardau

4

不能使用對數據成員的引用作爲模板參數:模板是編譯時,直到運行時才知道this的值。換句話說,您需要爲Test類型的每個運行時對象單獨實例化(單獨的二進制代碼)。

什麼你可以要做的就是更換ab一個數組,並templatise callee通過索引進入此陣:

class Test { 
    std::array<std::vector<int>, 2> ab; 
    void caller(...) { callee<0>(...); } 
    template <size_t idx> 
    void callee(...) { /* Do stuff with 'ab[idx]' */ } 
} 

這樣,你得到的callee(一個只有兩個實例爲0和一個用於1),並且在編譯時完成索引(或者至少可以)。

1

在相同的邏輯@ Angew的答案,你也可以使用std ::元組,這是相當有趣的,與元組,你也可以在被調用函數中使用不同類型的容器:

class Test { 
    std::tuple<std::vector<int>, std::list<int> > ab; 
    void caller(...) { callee<0>(...); } 
    template <size_t idx> 
    void callee(...) { 
    ... 
    auto aIt = std::get<idx>(ab).begin(); // gets either the vector or the list depending on template value 
    ... 
    } 
}