Использование алгоритмов STL (в частности, std :: sort) из шаблонного класса - PullRequest
2 голосов
/ 17 февраля 2010

Я объявил шаблонный класс MyContainer как ниже, а затем создал его экземпляр типа DataType1. Класс DataType1 предоставляет дружественную функцию «DataSpecificComparison», которая используется std :: sort для сравнения объектов DataType1. Программа скомпилирована и отсортирована правильно.

Затем я определил класс с именем DataType2, дал ему дружественную реализацию «DataSpecificComparison» и использовал его для создания другого экземпляра MyContainer.

Теперь я не могу скомпилировать программу как " C2914: 'std :: sort': не могу вывести аргумент шаблона, так как аргумент функции является неоднозначным " Сообщается об ошибке времени компиляции.

Как разработчик может указать, что двоичный предикат DataSpecificComparison должен принимать аргументы типа шаблона T *? Или есть другой способ обойти эту проблему?

template <class T>
class MyContainer
{
private: 
    vector<T*> m_vMyContainerObjects;
    ....

public:
    ....
    void SortMyContainerObjects()
    {
        std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison)
    }
}


class DataType1
{
    ....
    friend bool DataSpecificComparison(const DataType1 * lhs, const DataType1 * rhs)
}

class DataType2
{
    ....
    friend bool DataSpecificComparison(const DataType2* lhs, const DataType2* rhs)
}

Ответы [ 6 ]

6 голосов
/ 17 февраля 2010

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

void SortMyContainerObjects()
{
    typedef bool (*comparer_t)(const T*, const T*);
    comparer_t cmp = &DataSpecificComparison;
    std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), cmp);
}

Здесь компилятор может сделать вывод, что вы хотите использовать перегрузку DataSpecificComparison, соответствующую типу comparer_t, что разрешает неоднозначность.

3 голосов
/ 17 февраля 2010

STH уже дал правильный ответ, но есть и прямая альтернатива, основанная на том же принципе:

void SortMyContainerObjects()
{

    std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(),
       static_cast<bool (*comparer_t)(const T*, const T*)>(&DataSpecificComparison));
}

При этом используется практически тот же механизм. Разрешение приведения приводит к перегрузке шаблона до вычитания аргумента шаблона для std::sort.

1 голос
/ 17 февраля 2010

Я бы предпочел что-то в следующих строках: по умолчанию он сравнивает объекты с less_than (так что вам не нужно было бы указывать функцию с забавным именем), и есть перегрузка, которая позволяет дать свой собственный Функтор сравнения (опять же, на основе значений):

#include <vector>
#include <algorithm>
#include <functional>

template <class T, class Func>
struct indirect_binary_call_type: public std::binary_function<const T*, const T*, bool>
{
    Func f;
    indirect_binary_call_type(Func f): f(f) {}
    bool operator()(const T* a, const T* b) const
    {
        return f(*a, *b); 
    } 
};

template <class T, class Func>
indirect_binary_call_type<T, Func> indirect_binary_call(Func f)
{
    return indirect_binary_call_type<T, Func>(f);
}

template <class T>
class MyContainer
{
private: 
    std::vector<T*> m_vMyContainerObjects;

public:
    void Sort()
    {
        Sort(std::less<T>());
    }
    template <class Func>
    void Sort(Func f )
    {
        std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), indirect_binary_call<T>(f));
    }

};

int main()
{
    MyContainer<int> m;
    m.Sort();
    m.Sort(std::greater<int>());
}
1 голос
/ 17 февраля 2010
template<typename T>
struct DataSpecificComp : public binary_function<T, T, bool>
{
public:
    bool operator()(const T* lhs, const T* rhs)
    {
        return *lhs < *rhs;
    }
};

вызвать функцию сортировки, как показано ниже:

sort(vi.begin(), vi.end(), DataSpecificComp<int>());
0 голосов
/ 17 февраля 2010

Шаблоны DataSpecificComparison должны работать. Вы также можете специально назвать правильный шаблон std::sort, но он немного громоздок:

template <class T>
class MyContainer
{
private: 
    vector<T*> m_vMyContainerObjects;
    typedef bool (*compsT)(T, T); 

public:
    ....
    void SortMyContainerObjects()
    {
        std::sort<std::vector<T*>::iterator, compsT>(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison);
    }
}
0 голосов
/ 17 февраля 2010

Вы пытались определить DataSpecificComparison как шаблон с кучей специализаций и присвоить ему тип?

template<T>
bool DataSpecificComparison(const T* t1, const T* t2)
{
    // something non compilable here
}

template<> bool DataSpecificComparison<Data1>(const Data1* t1, const Data1* t2)
{
    // return *t1 < *t2;
}

....
void SortMyContainerObjects()
{
    std::sort(m_vMyContainerObjects.begin(), m_vMyContainerObjects.end(), DataSpecificComparison<T>)
}
....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...