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

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

pastryPrice()

что вызывает проблему — как вы можете видеть, я пытаюсь построить множество компараторов для одной функции шаблона сортировки

    struct dialingAreaComp{
inline bool operator()(const Deliver *d1, const Deliver *d2)const {
return d1->getDialingArea() < d2->getDialingArea();
}
};
struct pastryPrice {
inline bool operator()(const Pastry *p1, const Pastry *p2)const {
return p1->getPrice() < p2->getPrice();
}
};
template<class T>
void sortCollection(T& collection)
{
if ( typeid (collection) == typeid(vector <Deliver*>))
{
sort(collection.begin(), collection.end(), dialingAreaComp());
printCollection(collection);
}
else if (typeid (collection) == typeid(vector <Pastry*>))
{
sort(collection.begin(), collection.end(), pastryPrice());
printCollection(collection);
}
else { cout << "WRONG!"; }
}

Я получаю пять ошибок, все же:

Код серьезности Описание Состояние подавления строки файла проекта
Ошибка C2664 ‘bool Bakery :: pastryPrice :: operator () (const Pastry *, const Pastry *) const’: невозможно преобразовать аргумент 1 из ‘Deliver *’ в ‘const Pastry *’ Bakery c: \ программные файлы (x86) \ Microsoft Visual Studio 14.0 \ vc \ include \ xutility 809

И еще один:

Код серьезности Описание Состояние подавления строки файла проекта
Ошибка C2056 недопустимое выражение Bakery c: \ program files (x86) \ microsoft visual studio 14.0 \ vc \ include \ xutility 809

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

Сейчас:

C2264 — это ошибка компилятора, которая возникает, когда кто-то пытается передать функции параметр несовместимого типа.

Но функция Deliver работает, и когда я снял компаратор Deliver, также была скомпилирована Pastry … так что это за несовместимый тип?

1

Решение

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

void sortCollection(vector <Deliver*>& collection)
{
sort(collection.begin(), collection.end(), dialingAreaComp());
printCollection(collection);
}

void sortCollection(vector <Pastry*>& collection)
{
sort(collection.begin(), collection.end(), pastryPrice());
printCollection(collection);
}
4

Другие решения

Ваша проблема в том, что обе ветви компилируются независимо от того, какая из них занята.

Я бы подошел к этому по-другому.

template<class A, class B>
struct overload_t:A,B{
using A::operator();
using B::operator();
overload_t(A a, B b):A(std::move(a)), B(std::move(b)){}
};
template<class A, class B>
overload_t<A,B> overload( A a, B b ){
return {std::move(a),std::move(b)};
}

Это позволяет нам перегружать два функциональных объекта или лямбды. (Можно добавить совершенную пересылку, как и varargs …, но я сохранил это просто).

Теперь мы просто:

auto comp=overload(dialingAreaComp{}, pastryPrice{});
using std::begin; using std::end;
std::sort( begin(collection), end(collection), comp );

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

И прекратить использование using namespace std;,


То, что делает приведенный выше код, объединяет два ваших функциональных объекта в один. using A::operator() а также using B::operator() двигает оба () в тот же класс и говорит C ++ выбирать между ними при вызове с использованием обычных правил перегрузки вызова метода. Остальная часть кода — это клей, чтобы вывести типы, которые перегружены, и переместить-построить их.

sort звонки () с объектами определенного во время компиляции типа, основанного на типе контейнера. Разрешение перегрузки (в пределах sort в точке вызова) затем выбирает правильное тело для сравнения во время компиляции.

Таким образом, методика может быть расширена за счет поддержки более двух перегрузок, указателей функций и ссылок на пересылку. В C ++ 17 можно сделать некоторую работу, чтобы тип перегрузки определял родительские типы, устраняя необходимость в фабричной функции.

5

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector