5

私はクラスを定式化する方法を探しています:

  • 最大の「constness」を持つポインターの STL コンテナーを使用するインターフェイス
  • しかし、これは指されたオブジェクトを内部的に変更します
  • 非 const アナログと比較して余分なランタイム オーバーヘッドがない

理想的には、const/non-const-ness はここではプログラマーの補助にすぎないため、ソリューションは非 const バージョンと比較して余分なコードをコンパイルせずにコンパイルできます。

これが私がこれまでに試したことです:

#include <list>
#include <algorithm>

using namespace std;
typedef int T;

class C
{
public:
    // Elements pointed to are mutable, list is not, 'this' is not - compiles OK
    list<T *> const & get_t_list() const { return t_list_; }

    // Neither elements nor list nor' this' are mutable - doesn't compile
    list<T const *> const & get_t_list2() const { return t_list_; }

    // Sanity check: T const * is the problem - doesn't compile
    list<T const *> & get_t_list3() { return t_list_; }

    // Elements pointed to are immutable, 'this' and this->t_list_ are
    // also immutable - Compiles OK, but actually burns some CPU cycles
    list<T const *> get_t_list4() const {
        return list<T const *>( t_list_.begin() , t_list_.end() );
    }

private:
    list<T *> t_list_;
};

型変換の解決策がない場合は、説明されているプロパティを持つクラスを作成する方法について、代替案を提示してください。

4

2 に答える 2

7

少しの間、に変換できると仮定しましょlist<T*>&list<T const *>&。ここで、次のコードについて考えてみます。

list<char*> a;
list<char const*>& b = a;

b.push_back("foo");

a.front()[0] = 'x'; // oops mutating const data

T**これは、に変換する場合と同じ概念上の問題T const**です。

基になるデータへの読み取り専用アクセスを提供する場合は、場合によってはカスタムイテレーターを使用して、データのカスタムビューを提供する必要があります。

次のようなもの。

template <typename It>
class const_const_iterator {
private:
    using underlying_value_type = typename std::iterator_traits<It>::value_type;

    static_assert(std::is_pointer<underlying_value_type>(),
                  "must be an iterator to a pointer");

    using pointerless_value_type = typename std::remove_pointer<underlying_value_type>::type;

public:
    const_const_iterator(It it) : it(it) {}

    using value_type = pointerless_value_type const*;

    value_type operator*() const {
        return *it; // *it is a T*, but we return a T const*,
                    // converted implicitly
                    // also note that it is not assignable
    }

    // rest of iterator implementation here
    // boost::iterator_facade may be of help

private:
    It it;
};

template <typename Container>
class const_const_view {
private:
    using container_iterator = typename Container::iterator;

public:
    using const_iterator = const_const_iterator<container_iterator>;
    using iterator = const_iterator;

    const_const_view(Container const& container) : container(&container) {}

    const_iterator begin() const { return iterator(container->begin()); }
    const_iterator end() const { return iterator(container->end()); }

private:
    Container const* container;
}
于 2013-03-12T11:46:33.153 に答える
1

容器は返却しないでください。イテレータを返します。

于 2013-03-12T14:03:05.647 に答える