2016-11-07 88 views
0

我嘗試編寫一個通過其索引訪問容器中元素的類。因此,我將能夠重新路由所指向的容器(但對於我目前的問題,這並不重要)。它將幫助我擺脫複雜的拷貝構造函數。將轉換爲索引和指針並指向容器的類

這個類應該表現得好像它是一個數字(即索引),好像它是一個指針(即指向它)。因此我有轉換。然而我得到編譯器錯誤:

In instantiation of 'class paxRef<Dog&, std::vector<Dog> >': 
34:47: required from here 
13:5: error: forming pointer to reference type 'Dog&' 
In function 'int main()': 
37:7: error: base operand of '->' has non-pointer type 'paxRef<Dog&, std::vector<Dog> >' 
38:7: error: base operand of '->' has non-pointer type 'paxRef<Dog&, std::vector<Dog> >' 
44:43: error: base operand of '->' has non-pointer type 'paxRef<Dog&, std::vector<Dog> >' 
45:43: error: base operand of '->' has non-pointer type 'paxRef<Dog&, std::vector<Dog> >' 

forming pointer to reference type 'Dog&'是什麼意思?如果我有一個隱式轉換爲指針,我真的需要定義一個->運算符嗎?是否有可能縮短paxRef<decltype(v.back()), decltype(v)>語法,是否會導致上述錯誤?

這是我的代碼:

#include <iostream> 
#include <string> 
#include <vector> 

template <class T, class C> 
class paxRef 
{ 
public: 
    paxRef(size_t index, C* container) : _index(index), _container(container) { } 
    //implicit conversion 
    operator size_t() const { return _index; } 
    operator T*() { return &(_container->at(_index)); } 
    //operator ->() { return T*(); } // Do I need to define the -> operator if I already have a pointer-conversion operator? 
private: 
    size_t _index; 
    C* _container; 
}; 


class Dog 
{ 
public: 
    std::string bark() { return _sound; } 
    void setName(std::string sound) { _sound=sound; } 
private: 
    std::string _sound = "Wuff"; 
}; 


int main() 
{ 
    std::vector<Dog> v(5); 
    paxRef<decltype(v.back()), decltype(v)> r2(2, &v); // Very verbos. 
    paxRef<decltype(v.back()), decltype(v)> r4(4, &v); // Can I drop the <...> part somehow? 

    r2->setName("Bello"); 
    r4->setName("Fatty"); 

    for(size_t i{ 0 }; i<v.size(); ++i) 
     std::cout<<"Dog at "<<i<<" says "<<v.at(i).bark()<<std::endl; 

    std::cout<<std::endl; 
    std::cout<<"ref at "<<r2<<" says "<<r2->bark()<<std::endl; 
    std::cout<<"ref at "<<r4<<" says "<<r4->bark()<<std::endl; 
} 
+0

我懷疑你的實例化中使用了'decltype(v.back())'是不是你想要的那裏。我更傾向於使用'decltype(v):: value_type'來代替。你也可以使用'std :: remove_reference :: type',但老實說我不會看到這一點,除非你的拍攝模糊。我也傾向於爲你的容器成員使用引用而不是指針。 – WhozCraig

回答

1

是的,你需要明確定義operator->即使你有一個隱式轉換爲指針。

在 [over.match.oper]/2

如果一個操作數的一個類型,它是一個類或一個枚舉,一個用戶定義的運算功能可能是 標準狀態宣佈器具該操作符或用戶定義的轉換對於將操作數 轉換爲適合內置操作符的類型是必要的。在這種情況下,使用過載分辨率來確定要調用哪個運算符函數或內置運算符來實現運算符。 [...]

重載分辨率然後在[over.match.oper]/3,對於這種情況是[over.match.oper] /3.3的相關部分中描述:

對於operator,,一元operator &operator ->,內置候選集是空的。 [...]

這意味着,任何轉換,將允許在集結operator->到一個呼叫(在本例爲Dog*)被認爲是,而且必須有成員或非成員定義operator->爲您的班級。

關於模板參數明確標註: 您可以通過定義make_paxref類似make_tuplemake_pair,做類型推演模板化的輔助函數得到解決。或者你也可以等待C++ 17,其中模板參數推導也適用於模板類的構造函數:)

相關問題