2017-08-14 3 views
0

元々、クラス内でconst修飾子の有無にかかわらず宣言されたかどうかを推測したいと思っていました。多くの人が指摘しているように、変数自体はconst(クラスではない)として宣言されています。これを明確にしてくれてありがとう。エラーメッセージは完全に私には分かります。だから、それは設計上の問題です。GCC7同じクラスでconst修飾子が存在しないようにする

ランダムアクセスコンテナのように動作し、iterator begin(){...},const_iterator cbegin(){...}、特にvalue_type operator[](size_type idx){...}などのいくつかの機能を提供する構造体が必要です。インスタンスがconstかどうかにかかわらず、可能な限り多くの関数を提供したいと思います。したがって、実際にはA a{}; a.begin();は、Aa.cbegin()という値型の非定数参照をconst参照として返します。一方、A const ac{};ac.begin()およびac.cbegin()は、同じ定数参照型を持つ必要があります。しかしおそらく、これらのユースケースは意味をなさないでしょう。 I(すなわちa.begin()はなくa.cbegin()を可能)、およびのみCONST反復子(すなわちac.cbegin()はなく、ac.begin())とac非constイテレータとの組み合わせでのみ非const aが呼び出し可能であるケースを使用することに制限できました。これは意味がありますか?

この奇妙な試みの背後にある理由は、私の実装では、基本的なコンテナは1つではなく、2つのヘルパーコンテナが存在することです。ビットベクトルと圧縮されたシーケンスです。ビットベクトルの内容に応じて、特殊記号または圧縮されたシーケンスの文字を返します(拡張コードの例を参照)。 また、私はstd :: iteratorを使用せず、独自の実装を使用します。注意(*host)[idx + offset]は一時的な結果を返します。これはおそらく、出力の後にセグメンテーション違反が発生する理由です。

#include <cassert> 
#include <iostream> 
#include <numeric> 
#include <type_traits> 
#include <vector> 

template<typename container_t> 
struct my_iterator 
{ 
private: 
    using reference = std::conditional_t<std::is_const<container_t>::value, 
        typename container_t::const_reference, 
        typename container_t::reference>; 
    using size_type = typename container_t::size_type; 
    size_type offset = 0; 
    typename std::add_pointer_t<container_t> host{nullptr}; 
public: 
    my_iterator(container_t & host_, size_type offset_) : host{&host_}, offset{offset_} {} 
    reference operator[](typename container_t::size_type const idx) 
    { 
     return (*host)[idx + offset]; 
    } 
}; 

template<typename sequence_t> 
struct A // implements some features of the container concept 
{ 
    using const_reference = typename sequence_t::const_reference; 
    using reference = typename sequence_t::value_type; 
    using iterator = my_iterator<A>; 
    using const_iterator = my_iterator<A const>; 
    using value_type = typename sequence_t::value_type; 
    using size_type = typename sequence_t::size_type; 

    // data structures internally used to resolve random access 
    std::vector<unsigned int> bit_vector{1,0,1,0,0,0}; 
    std::vector<char> text{'h', 'w'}; 
    constexpr char static const cash = '$'; 

public: 
    // provide some container functions, like begin, end, cbegin, cend 
    iterator begin() 
    { 
     return iterator{*this, 0}; 
    } 

    const_iterator cbegin() const 
    { 
     return const_iterator{*this, 0}; 
    } 
    // ... 

    size_type rank(size_type idx) const 
    { 
     return std::accumulate(bit_vector.begin(), bit_vector.begin()+idx, 0); 
} 

constexpr reference operator[](size_type const idx) const 
{ 
    assert(idx < bit_vector.size()); 
    if (bit_vector[idx]) 
     return cash; 
    return text[idx - rank(idx)]; 
} 
}; 

int main(){ 
    /* non const usage */ 
    A<std::vector<char>> a{}; 
    auto it_a = a.begin(); 
    std::cout << it_a[0] << std::endl; 
    /* const usage */ 
    A<std::vector<char>> const a_const{}; 
    /* does not compile, because of non matching types */ 
    auto it_const_a = a_const.begin(); 
    std::cout << "it_const_a[0] = " << it_const_a[1] << std::endl; 
    /* does compile, but gives segmentation fault */ 
    auto it_const_a2 = a_const.cbegin(); 
    std::cout << "it_const_a2[0] = " << it_const_a2[1] << std::endl; 
} 
+3

'this'はメンバー関数内にのみ存在します。それはオブジェクトが自身の存在を認識している唯一の状況です。これを望んでいるあなたの理由は少し奇妙に聞こえる。これと '[] '演算子のオーバーロードの関係を説明すると、実際の問題を解決するための助けを得ることができます。 – molbdnilo

+0

また、 'A > a();'は 'A >'を返す関数の宣言です。代わりに 'A > a;'と書くべきです。 – WindyFields

+0

'const'はクラスにではなく変数に適用されるので、あなたが提案していることはできません。しかし、これは間違いなくX-Yの問題のようです。あなたが何をしているのかははっきりしていませんが、 'ret_type1 operator [](size_t);と' ret_type2 operator [](size_t)const; 'オーバーロードだけで必要なものを得ることができます。 – aschepler

答えて

2

私はそれがまたはconstの修飾子なしで宣言されたかどうかをクラス内で推測したいと思います。 const修飾子で宣言されていない

クラス。これらの修飾子は、の変数の宣言用です。

エラーメッセージに説明されているように、非スタティックメンバー関数以外にはthisがありません。クラスのメンバ型(別名)はインスタンスに依存しないため、インスタンスの定数に依存することはできません。

いずれにしても、私はあなたがstd::iteratorを反復子と想定していると思われます。 ではなく、イテレータです。これは、(カスタム)イテレータを書くときにいくつかの定義を繰り返さないようにするために使用できる基本クラスです。そして、このような混乱は、今後の標準バージョンでは廃止される可能性が高いでしょう。

関連する問題