Biorąc pod uwagę następujące elementy:Czy mogę napisać funktor C++, który akceptuje zarówno surowy wskaźnik, jak i inteligentny wskaźnik?
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;
}
};
mam pojemnik Foo*
i używam std::find_if
i std::not1
, aby dowiedzieć się, czy są jakieś elementy w pojemniku, w którym bar()
powraca czymś różni się od podanej wartości. Kod wygląda następująco:
// 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();
}
Przewijanie do przodu w przyszłość i teraz mam inny pojemnik, tym razem zawierająca std::tr1::shared_ptr<Foo>
. Chciałbym po prostu ponownie użyć mojego funktora w przeładowanej wersji isAllEqual()
. Ale nie mogę. Foo*
i shared_ptr<Foo>
to różne typy. I muszę odziedziczyć po unary_function
, więc mogę użyć not1
. Byłoby bardziej elegancko, gdybym dwukrotnie unikał pisania tego samego funktora.
Pytania:
- Czy istnieje jakiś sposób, aby napisać
IsEqual
więc można go używać zarówno surowych i inteligentne kursory? - Czy założyłem sobie kajdanki przy użyciu
std::not1
? Czy powinienem zamiast tego napisaćIsNotEqual
?
Ograniczenia:
- Nie mogę używać niczego z biblioteki boost.
- Nasz kompilator nie jest wystarczająco fajny, aby obsługiwać lambdy w C++ 0x.
To brzmi jak przykład, gdzie szablony byłyby miłe. – GWW
@Kristo: Czy Twój kompilator jest wystarczająco fajny, aby zapewnić inne rzeczy w C++ 0x, takie jak 'std :: begin'? –
@Ben, używamy gcc 4.1.2, więc prawdopodobnie nie. 'std :: begin' i' std :: end' powinny być trywialne, aby pisać. –