2016-11-07 13 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.3である、[over.match.oper]/3に記載されていますoperator,、単一operator &、またはoperator ->の場合、ビルトイン候補セットは空です。 [...]

これは、ビルドインoperator->Dog*ため、この場合)への呼び出しを可能にするいかなる変換を考慮しない、との会員または非会員の定義がなければならないことを意味していますあなたのクラスはoperator->です。テンプレート引数を明示的に注釈について

: あなたは型推論を行いmake_tuplemake_pairに似たテンプレートヘルパー関数make_paxrefを定義することによって、その周りを取得することができます。あるいは、テンプレート引数の減算がテンプレートクラスのコンストラクタでも機能するC++ 17を待つことができます:)

関連する問題