C ++: Менять местами элементы класса шаблона? - PullRequest
3 голосов
/ 10 мая 2010
template< class T1, class T2 >
class Pair {
    T1 first;
    T2 second;
};

Меня просят написать метод swap (), чтобы первый элемент стал вторым, а второй - первым. У меня есть:

Pair<T2,T1> swap() {
    return Pair<T2,T1>(second, first);
}

Но это возвращает новый объект, а не обмен, где я думаю, что это должен быть пустой метод, который изменяет свои собственные члены данных. Возможно ли это сделать, поскольку T1 и T2 потенциально разные типы классов? Другими словами, я не могу просто установить temp = first, first = second, second = temp, потому что он попытается преобразовать их в разные типы. Я не уверен, почему вы потенциально хотели бы иметь объект шаблона, который изменяет порядок его типов, поскольку это может вызвать путаницу, но, похоже, это то, что меня просят сделать.

Редактировать: Спасибо всем за ответы! Как я и думал, замена на месте, очевидно, не имеет никакого смысла, запрос на функцию swap () был довольно неоднозначным.

Ответы [ 3 ]

8 голосов
/ 10 мая 2010

Вы не можете поменять на месте , поскольку T1 и T2 не обязательно должны быть одного типа. Pair<T1,T2> отличается от Pair<T2,T1>. Вы должны вернуть объект другого типа, чем исходный, так что это должен быть новый объект.

Что бы я сделал, это:

template< class T1, class T2 >
Pair<T2,T1> swap(const Pair<T1,T2>& pair) {
    return Pair<T2,T1>(pair.second, pair.first);
}

(Нет причин делать это элементом вашего Pair шаблона.)

Однако вы можете добавить перегрузку для случаев, когда T1 и T2 относятся к одному и тому же типу:

template< class T >
Pair<T,T>& swap(Pair<T,T>& pair) {
    using std::swap;
    swap(pair.first, pair.second);
    return pair;
}

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

Другая идея состоит в том, чтобы определить конструктор преобразования для вашего Pair шаблона, чтобы неявно конвертируемые типы могли быть заменены:

template< class T1, class T2 >
class Pair {
    T1 first;
    T2 second;
    template< class A1, class A2 >
    Pair(const A1& a1, const A2& a2) : first(a1), second (a2) {}
};

Тогда вы можете поменять местами вот так:

Pair<int,double> p1(42,47.11);
Pair<double,int> p2(p1.second,p1.first);

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

Pair<char,float> p3(p1.second, p1.first); // narrowing! 
2 голосов
/ 10 мая 2010

Обмен возможен только в том случае, если T1 может быть преобразован в T2 и наоборот. Если это возможно, вы можете написать

T2 temp (first);
first = T1(second);
second = temp;

(Обратите внимание, что вы не можете изменить *this с Pair<T1,T2> на Pair<T2,T1> с помощью этой функции void.)

1 голос
/ 10 мая 2010

Поскольку pair <T1,T2> и pair <T2,T1> - это разные типы, вы не можете использовать своп на него. Сам своп также не делает намного больше, чем использование временной переменной, когда не предусмотрена встроенная операция свопинга (например, в std::vector есть такая). Однако вы можете создать новый тип, используя ссылки. Или вы используете указатели, где копирование дешево.

    std::pair<int, float> a = std::pair <int, float> (3,3.5);
    std::pair<const float &, const int&> b = std::pair<const float &, const int&> (a.first, a.second);
...