Присвоение контейнера STL и указатели константы

Для тех, кто ищет общий способ работы с ListBox, который может быть связан с источником данных, вот общее расширение, основанное на ответе Save , которое будет обрабатывать обычный и связанный ListBox.

public static void MoveUp(this ListBox listBox)
{
    listBox.MoveItem(-1);
}

public static void MoveDown(this ListBox listBox)
{
    listBox.MoveItem(1);
}

public static void MoveItem(this ListBox listBox, int direction)
{
    // Checking selected item
    if (listBox.SelectedItem == null || listBox.SelectedIndex < 0)
        return; // No selected item - nothing to do

    // Calculate new index using move direction
    int newIndex = listBox.SelectedIndex + direction;

    // Checking bounds of the range
    if (newIndex < 0 || newIndex >= listBox.Items.Count)
        return; // Index out of range - nothing to do


    //Find our if we're dealing with a BindingSource
    bool isBindingSource = listBox.DataSource is BindingSource;

    //Get the list
    System.Collections.IList list = isBindingSource ? ((BindingSource)listBox.DataSource).List : listBox.Items;

    object selected = listBox.SelectedItem;

    // Removing removable element
    list.Remove(selected);

    // Insert it in new position
    list.Insert(newIndex, selected);

    // Restore selection
    listBox.SetSelected(newIndex, true);

    if (isBindingSource)
    {
        //Reset the binding if needed
        ((BindingSource)listBox.DataSource).ResetBindings(false);
    }

}

10
задан Steffen Opel 27 July 2009 в 13:56
поделиться

7 ответов

Direct assignment is not possible. As others explained, the equivalence is not established by the pointer types, but by the container types. In this case, vector doesn't want to accept another vector that has a different, but compatible element type.

No real problem, since you can use the assign member function:

v2.assign(v1.begin(), v1.end());
43
ответ дан 3 December 2019 в 13:11
поделиться

Проблема не в указателях , но типы двух векторов. Стандартных преобразований между шаблонными типами, подобными преобразованиям v1 и v2 в вашем примере, нет.

Это, возможно, легче увидеть в следующем коде:

20
ответ дан 3 December 2019 в 13:11
поделиться

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

template <class A>
vector2<T> &operator=(const vector2<A> &other)
{
    assign(other.begin(), other.end());
    return *this;
}

Где T - тип элемента всего класса, тогда как A - любой тип, присваиваемый T .

Мне непонятно, почему std :: vector не имеет этого.

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

Проблема не в указателях, а в типах два вектора. Стандартных преобразований между шаблонными типами, такими как v1 и v2 в вашем примере, нет.

Возможно, это легче увидеть в следующем коде:

#include <vector>
using namespace std;

int main() {
    vector <char> cv;
    vector <int> iv;
    cv = iv;    // error
}
7
ответ дан 3 December 2019 в 13:11
поделиться

В шаблонных классах C ++ каждый экземпляр шаблона представляет собой совершенно другой класс - такая же большая разница между vector и vector как есть между vector и vector или любыми другими двумя классами в этом отношении.

Возможно, что комитет мог бы добавить оператор преобразования для вектора в vector , как предлагает Эрвикер - и вы можете продолжить и предоставьте свою собственную реализацию такой функции:

template <class A, class T>
vector<T> convert_vector(const vector<A> &other)
{
    vector<T> newVector;
    newVector.assign(other.begin(), other.end());
    return newVector;
}

и используйте ее так:

vector<int*> v1;
vector<const int*> v2;
v2 = convert_vector<const int*>(v1);

К сожалению, до тех пор, пока C ++ 0x не будет поставляться с конструкторами перемещения, это будет очень плохо с точки зрения производительности.

4
ответ дан 3 December 2019 в 13:11
поделиться

Опасно, если вы не знаете, что типы абсолютно совместимы:

v2 = reinterpret_cast &> (v1);

Большинство реализаций STL действительно используют специализацию, когда все векторы указатели используют одну и ту же базовую реализацию. Это потому, что (void *) обычно имеет тот же размер, что и (int *) или любой другой тип указателя.

2
ответ дан 3 December 2019 в 13:11
поделиться

Принуждение шаблоном члена идиома - один из возможных подходов к решению проблемы. По сути, добавлен оператор копирования-присваивания шаблона элемента, который позволяет классу шаблона участвовать в тех же неявных преобразованиях типов (принуждение), которые в противном случае возможны только для параметров типа шаблона класса. Хотя идиома используется в STL в других местах, она недоступна в std :: vector.

1
ответ дан 3 December 2019 в 13:11
поделиться
Другие вопросы по тегам:

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