Как я стираю reverse_iterator из stl структуры данных?

Если вы хотите установить точность для всех decimals в EF6, вы можете заменить стандартное соглашение DecimalPropertyConvention, используемое в DbModelBuilder:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<DecimalPropertyConvention>();
    modelBuilder.Conventions.Add(new DecimalPropertyConvention(38, 18));
}

По умолчанию DecimalPropertyConvention в EF6 отображает свойства decimal в столбцы decimal(18,2).

Если вы хотите, чтобы отдельные свойства имели заданную точность, вы можете установить точность для свойства объекта в DbModelBuilder:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>().Property(e => e.Value).HasPrecision(38, 18);
}

Или добавьте EntityTypeConfiguration<> для объекта, который задает точность:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new MyEntityConfiguration());
}

internal class MyEntityConfiguration : EntityTypeConfiguration<MyEntity>
{
    internal MyEntityConfiguration()
    {
        this.Property(e => e.Value).HasPrecision(38, 18);
    }
}
14
задан Doug T. 31 December 2008 в 23:27
поделиться

3 ответа

По-видимому, решение - то, какая основа () возвраты 1 прочь. Следующие идентификационные данные содержат для reverse_iterator:

&*(reverse_iterator(i)) == &*(i - 1) 

Или другими словами, reverse_iterator всегда является одной передачей регулярный итератор, из которого это является основа. Не уверенный, почему.

В GCC

Просто изменяются

        // SEGFAULT HERE
        setOfInts.erase( rev_iter.base());

к [1 110]

        // WORKS!
        setOfInts.erase( --rev_iter.base());

, мне определенно любопытно, хотя относительно того, почему идентификационные данные выше имеют смысл.

В Visual Studio

, Возвращающемся в работу и пробующем это в Visual Studio, я вижу, что вышеупомянутое решение не вполне работает. "nextIter" становится недопустимым на стирании. Вместо этого необходимо сохранить далеко временный файл от стирания для получения следующего итератора вместо того, чтобы иметь в наличии nextIter как вышеупомянутый.

  set<int>::iterator tempIter = setOfInts.erase(--rev_iter.base());
  rev_iter = setOfInts.erase(tempIter);

, Таким образом, конечное решение

int main()
{
    using namespace std;

    set<int> setOfInts;
    setOfInts.insert(1);
    setOfInts.insert(2);
    setOfInts.insert(3);

    set<int>::reverse_iterator rev_iter = setOfInts.rbegin();

    while ( rev_iter != setOfInts.rend())
    {
        // Find 3 and try to erase
        if (*rev_iter == 3)
        {
            cout << "Erasing : " << *rev_iter;
            set<int>::iterator tempIter = setOfInts.erase( --rev_iter.base());
            rev_iter = set<int>::reverse_iterator(tempIter);            
        }
        else
        {
            ++rev_iter;
        }
    }   

}

Примечание, ассоциативные контейнеры не возвращают итератор из стирания. Таким образом, это решение не работало бы на карту, мультикарту, и т.д.

18
ответ дан 1 December 2019 в 13:34
поделиться

Звоните erase с самим итератором (никакая потребность использовать base).

#include <set>
#include <iostream>

int main()
{
    std::set<int> setOfInts;
    setOfInts.insert(1);
    setOfInts.insert(2);
    setOfInts.insert(3);

    std::set<int>::reverse_iterator rev_iter = setOfInts.rbegin();

    while (rev_iter != setOfInts.rend())
    {
        // Find 3 and try to erase
        if (*rev_iter == 3)
        {
            rev_iter = setOfInts.erase(rev_iter);
        }
        else
        {
            ++rev_iter;
        }
    }
}

кроме того, Вам не нужен тот отдельный "следующий" итератор (см. выше изменений). Еще лучший способ сделать это должно использовать std::remove_if (или функция как он).

-3
ответ дан 1 December 2019 в 13:34
поделиться

Когда вы выполняете итерацию с обратным итератором и хотите использовать base () для изменения его контейнера, всегда сохраняйте в виду, что reverse_iterator всегда основан на следующем итераторе из исходного порядка. Это немного неинтуитивно, но на самом деле упрощает код:

#include <set>
int main()
{
    std::set<int> setOfInts;
    setOfInts.insert(1);
    setOfInts.insert(2);
    setOfInts.insert(3);

    typedef std::set<int>::reverse_iterator RevIter;

    RevIter rev_iter = setOfInts.rbegin();
    while (rev_iter != setOfInts.rend())
    {
        // Find 3 and try to erase
        if (*rev_iter == 3)
            setOfInts.erase(--rev_iter.base());

        ++rev_iter;
    }
}

В этом примере нет необходимости сохранять «следующий» итератор, поскольку базовый итератор не аннулируется! (Нам это действительно нужно при работе с обычными итераторами.)

Поведение обратных итераторов создает странные постепенные трудности при работе с одним элементом, но на самом деле оно упрощает диапазоны:

riValue = find(riEnd.base(), riBegin.base(), value);

использует в точности те же объекты (в обратном порядке), что и

iValue = find(riBegin, riEnd, value);
3
ответ дан 1 December 2019 в 13:34
поделиться
Другие вопросы по тегам:

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