Учитывая следующее:Могу ли я написать функтор C++, который принимает как необработанный указатель, так и умный указатель?
struct Foo
{
int bar() const;
};
struct IsEqual : public std::unary_function<Foo*, bool>
{
int val;
IsEqual(int v) : val(v) {}
bool operator()(const Foo* elem) const
{
return elem->bar() == val;
}
};
У меня есть контейнер Foo*
и я использую std::find_if
и std::not1
, чтобы выяснить, есть ли какие-либо элементы в контейнере, где bar()
возвращается нечто отличное от заданного значения. Код выглядит следующим образом:
// Are all elements equal to '2'?
bool isAllEqual(const std::vector<Foo*> &vec)
{
return find_if(vec.begin(), vec.end(), std::not1(IsEqual(2))) == vec.end();
}
Перемотка вперед в будущее, и теперь у меня есть другой контейнер, содержащий этот раз std::tr1::shared_ptr<Foo>
. Я бы хотел просто повторно использовать мой функтор в перегруженной версии isAllEqual()
. Но я не могу. Foo*
и shared_ptr<Foo>
- это разные типы. И мне нужно наследовать от unary_function
, поэтому я могу использовать not1
. Было бы более элегантно, если бы я мог дважды написать тот же самый функтор.
Вопросы:
- Есть ли способ, чтобы написать
IsEqual
так что он может использовать как сырье и смарт-указатели? - Я сам надел наручники, используя
std::not1
? Должен ли я просто написатьIsNotEqual
?
Ограничения:
- Я ничего не могу из библиотеки повышающего использовать.
- Наш компилятор не достаточно крут, чтобы поддерживать C++ 0x lambdas.
Это звучит как пример, где шаблоны были бы хороши. – GWW
@Kristo: Является ли ваш компилятор достаточно крутым, чтобы предоставить другой материал C++ 0x, например 'std :: begin'? –
@Ben, мы используем gcc 4.1.2, поэтому, вероятно, нет. «std :: begin» и 'std :: end' должны быть тривиальны для записи. –