Для тех, кто ищет общий способ работы с 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);
}
}
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());
Проблема не в указателях , но типы двух векторов. Стандартных преобразований между шаблонными типами, подобными преобразованиям v1 и v2 в вашем примере, нет.
Это, возможно, легче увидеть в следующем коде:
Было бы вполне возможно написать свою собственную версию вектора
там, где это было возможно. Он был бы идентичен стандартному типу, но с шаблонной версией operator =
, примерно так:
template <class A>
vector2<T> &operator=(const vector2<A> &other)
{
assign(other.begin(), other.end());
return *this;
}
Где T - тип элемента всего класса, тогда как A - любой тип, присваиваемый T .
Мне непонятно, почему std :: vector
не имеет этого.
Проблема не в указателях, а в типах два вектора. Стандартных преобразований между шаблонными типами, такими как v1 и v2 в вашем примере, нет.
Возможно, это легче увидеть в следующем коде:
#include <vector>
using namespace std;
int main() {
vector <char> cv;
vector <int> iv;
cv = iv; // error
}
В шаблонных классах 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 не будет поставляться с конструкторами перемещения, это будет очень плохо с точки зрения производительности.
Опасно, если вы не знаете, что типы абсолютно совместимы:
v2 = reinterpret_cast
Большинство реализаций STL действительно используют специализацию, когда все векторы указатели используют одну и ту же базовую реализацию. Это потому, что (void *) обычно имеет тот же размер, что и (int *) или любой другой тип указателя.
Принуждение шаблоном члена идиома - один из возможных подходов к решению проблемы. По сути, добавлен оператор копирования-присваивания шаблона элемента, который позволяет классу шаблона участвовать в тех же неявных преобразованиях типов (принуждение), которые в противном случае возможны только для параметров типа шаблона класса. Хотя идиома используется в STL в других местах, она недоступна в std :: vector.