Как удалить constness const_iterator?

Вы можете использовать селектор css n-типа

h1 span:nth-of-type(2)

, т.е.

items = soup.select("h1 span:nth-of-type(2)")

Затем итерируйте список.

Если возможно только одно совпадение, то просто:

item = soup.select_one("h1 span:nth-of-type(2)")
print(item.text.strip())
43
задан Community 23 May 2017 в 12:09
поделиться

7 ответов

К сожалению, линейное время - единственный способ сделать это:

iter i(d.begin());
advance (i,distance<ConstIter>(i,ci));

где iter и constIter являются подходящими typedefs, а d - контейнер, по которому вы перебираете.

14
ответ дан 26 November 2019 в 22:44
поделиться

Возможно, это не тот ответ, который вы хотели, а несколько связанный.

Полагаю, вы хотите изменить ситуацию где итератор указывает на. Самый простой способ сделать это - вместо этого const_cast вернуть возвращенную ссылку.

Что-то вроде этого

const_cast (* it);

3
ответ дан 26 November 2019 в 22:44
поделиться

Я считаю, что это преобразование не нужно в хорошо разработанной программе.

Если вам нужно сделать это - попробуйте изменить код.

В качестве обходного пути вы можете сделать следующее:

typedef std::vector< size_t > container_type;
container_type v;
// filling container code 
container_type::const_iterator ci = v.begin() + 3; // set some value 
container_type::iterator i = v.begin();
std::advance( i, std::distance< container_type::const_iterator >( v.begin(), ci ) );

Но я думаю, что иногда это преобразование невозможно, потому что ваши алгоритмы могут не иметь доступа к контейнеру.

2
ответ дан 26 November 2019 в 22:44
поделиться

Вы можете вычесть итератор begin () из const_iterator, чтобы получить позицию, на которую указывает const_iterator, а затем добавить начало () вернуться к этому, чтобы получить неконстантный итератор. Я не думаю, что это будет очень эффективно для нелинейных контейнеров, но для линейных, таких как вектор, это займет постоянное время.

vector<int> v;                                                                                                         
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
vector<int>::iterator it = v.begin() + (ci - v.begin());
cout << *it << endl;
*it = 20;
cout << *ci << endl;

РЕДАКТИРОВАТЬ : Это работает только для линейных контейнеров (произвольного доступа).

1
ответ дан 26 November 2019 в 22:44
поделиться

вы можете преобразовать свой указатель значения константного итератора в неконстантный указатель значения и использовать его непосредственно как-то так

    vector<int> v;                                                                                                         
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(2);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
*const_cast<int*>(&(*ci)) = 7;
cout << *ci << endl;
0
ответ дан 26 November 2019 в 22:44
поделиться

In the answers to your previous post, there were a couple of people, me included, that recommended using const_iterators instead for non-performance related reasons. Readability, traceability from the design board to the code... Using const_iterators to provide mutating access to a non-const element is much worse than never using const_iterators at all. You are converting your code into something that only you will understand, with a worse design and a real maintainability pain. Using const just to cast it away is much worse than not using const at all.

If you are sure you want it, the good/bad part of C++ is that you can always get enough rope to hang yourself. If your intention is using const_iterator for performance issues, you should really rethink it, but if you still want to shoot your foot off... well C++ can provide your weapon of choice.

First, the simplest: if your operations take the arguments as const (even if internally apply const_cast) I believe it should work directly in most implementations (even if it is probably undefined behavior).

If you cannot change the functors, then you could tackle the problem from either side: provide a non-const iterator wrapper around the const iterators, or else provide a const functor wrapper around the non-const functors.

Iterator façade, the long road:

template <typename T>
struct remove_const
{
    typedef T type;
};
template <typename T>
struct remove_const<const T>
{
    typedef T type;
};

template <typename T>
class unconst_iterator_type
{
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef typename remove_const<
                typename std::iterator_traits<T>::value_type
            >::type value_type;
        typedef value_type* pointer;
        typedef value_type& reference;

        unconst_iterator_type( T it )
            : it_( it ) {} // allow implicit conversions
        unconst_iterator_type& operator++() {
            ++it_;
            return *this;
        }
        value_type& operator*() {
            return const_cast<value_type&>( *it_ );
        }
        pointer operator->() {
            return const_cast<pointer>( &(*it_) );
        }
        friend bool operator==( unconst_iterator_type<T> const & lhs,
                unconst_iterator_type<T> const & rhs )
        {
            return lhs.it_ == rhs.it_;
        }
        friend bool operator!=( unconst_iterator_type<T> const & lhs,
                unconst_iterator_type<T> const & rhs )
        {
            return !( lhs == rhs );
        }
    private:
        T it_;  // internal (const) iterator
};
4
ответ дан 26 November 2019 в 22:44
поделиться

Статья Скотта Мейера о предпочтении итераторов над const_iterators отвечает на этот вопрос. Ответ Visage - единственная безопасная альтернатива до C ++ 11, но на самом деле это постоянное время для хорошо реализованных итераторов произвольного доступа и линейное время для других.

4
ответ дан 26 November 2019 в 22:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: