Не удалось специализировать шаблон функции - PullRequest
5 голосов
/ 08 января 2011

Это домашнее задание, хотя оно уже представлено с другим подходом.

Я получаю следующее от Visual Studio 2008

error C2893: Failed to specialize function template 'void std::sort(_RanIt,_RanIt,_Pr)'

Код выглядит следующим образом

main.cpp
    Database<> db; 
    db.loadDatabase();
    db.sortDatabase(sort_by_title());  

Database.cpp
void Database<C>::sortDatabase(const sort_by &s) { 
    std::sort(db_.begin(), db_.end(), s); 
}

И функциональные объекты определены как

struct sort_by : public std::binary_function<const Media *, const Media *, bool> { 
    virtual bool operator()(const Media *l, const Media *r) const = 0;
};

struct sort_by_title : public sort_by {
    bool operator()(const Media *l, const Media *r) const { ... }
};
...

Какое лекарство здесь?

[Изменить] Извините, может быть, я должен был сделать наследство ясным

template <typename C = std::vector<Media *> >
class Database : public IDatabase<C> 

[/ Edit]

[Edit2]
После предложения от Toolbox (которое казалось очень разумным) я получил следующее сообщение об ошибке

error C2664: 'Database<>::sortMedia' : cannot convert parameter 1 from 'sort_by_title' to 'const sort_by &'

main.cpp остается тем же, но с некоторыми небольшими изменениями в иерархии функторов и исходных файлах. Предварительные объявления и тому подобное не работали, поэтому мне пришлось поместить определения в отдельные файлы.

Search.h
struct sort_by_impl {
    virtual bool operator()(const Media *l, const Media *r) const = 0;
};
struct sort_by : public std::binary_function<const Media *, const Media *, bool> { 
    sort_by_impl *sbp;
    bool operator()(const Media *l, const Media *r) const {
        return (*sbp)(l, r);
    }
};

IDatabase.h
struct sort_by_title : public sort_by_impl {
    bool operator()(const Media *l, const Media *r) const {
        return (l->getTitle() < r->getTitle());
    }
};

Я правда не ворчу, что мне здесь не хватает? Какая-то операция преобразования или как?
[/ Edit2]

[Edit3]
Последнее и окончательное редактирование, я надеюсь. Я на самом деле получил это после отладки и переписывания кода. Это то, чем я закончил, и это лучшее, что я мог сделать

class sort_by : public std::binary_function<const Media *, const Media *, bool> { 
public:
    sort_by(sort_by_impl *sbp) : sbp_(sbp) {};
    bool operator()(const Media *l, const Media *r) const {
        return (*sbp_)(l, r);
    }
private:
    sort_by_impl *sbp_;
};

main.cpp
    db.sortDatabase(&sort_by_title());

Database.cpp
void Database<C>::sortDatabase(const sort_by &s) { 
    std::sort(db_.begin(), db_.end(), s); 

Кажется, это работает, как в отдельном проекте (потратив большую часть этого дня на это), так и в моем реальном проекте, который я представил несколько дней назад.
Большое спасибо за ваше время и помощь!
[/ Edit3]

1 Ответ

8 голосов
/ 08 января 2011

Я не уверен, что это является причиной проблемы, так как это не имеет ничего общего со специализацией std::sort, но в sortDatabase вы не должны передавать функтор, который должен вести себя полиморфно. Причина в том, что std::sort принимает ваш функциональный объект по значению, что означает, что он копируется как sort_by объект, а не то, чем он является на самом деле (т. Е. У вас есть проблема с нарезкой).

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

struct sort_by : public std::binary_function<const Media*, const Media*, bool> {
    bool operator()(const Media *l, const Media *r) const
    {
        return (*p_impl)(l, r);
    }

    sort_by_impl* p_impl;
};

Тогда sort_by_impl может быть вашим абстрактным базовым классом, из которого происходят и переопределяются конкретные объекты функции сортировки. Надеюсь, это поможет.

EDIT

Исходя из нового сообщения об ошибке, если бы мне пришлось угадывать, вы пытаетесь сделать что-то подобное внутри sortMedia:

Database<std::vector<Media*> > db; // initialized elsewhere...

sort_by_title my_sort;
db.sortDatabase(my_sort);

Проблема в том, что my_sort имеет тип sort_by_title, который является производной формой sort_by_impl - , а не типа sort_by. Это означает, что вы действительно хотите передать my_sort в качестве указателя sbp в sort_by объекте, который является фактическим функциональным объектом, который вы будете использовать. Для иллюстрации:

Database<std::vector<Media*> > db; // initialized elsewhere...

sort_by my_sort_fn;
my_sort_fn.sbp = new sort_by_title;
db.sortDatabase(my_sort_fn);

delete my_sort_fn.sbp;

Между прочим, код не исключительный; рассмотрите возможность замены sbp интеллектуальным указателем для подсчета ссылок. Или даже проще, просто объявите sort_by_title в стеке и передайте его адрес. Просто будьте осторожны, чтобы не допустить его уничтожения перед использованием. :)

Надеюсь, это поможет. Дайте мне знать, как это получается!

...