I have a custom read-only data structure that I need to transverse. I would like to create a custom iterator that need to skip certain values.
A simple but equivalent example would be the following. I have a vector of numbers and I want to loop through all skipping the negative values. Normally I would do something like:
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
if (*it > 0) {
dosomething(*it);
}
}
But I would like to do something like:
vector<int> v;
for (vector<int>::my_iterator it = v.my_begin(); it!=v.my_end(); ++it) {
dosomething(*it);
}
What is the right way to achieve this?
This is easily achieved with a boost::filter_iterator, if your data structure already stores a container under the hood. Here's a simple example:
#include <vector>
#include <iostream>
#include <boost/iterator/filter_iterator.hpp>
class X{
typedef std::vector<int> container;
struct Pred{
bool operator()(int i){
return i % 2 == 0;
}
};
public:
typedef boost::filter_iterator<Pred, container::iterator> iterator;
void add(int val){ nums.push_back(val); }
iterator begin(){ return iterator(nums.begin(), nums.end()); }
iterator end(){ return iterator(nums.end(), nums.end()); }
private:
container nums;
};
int main(){
X x;
for(int i=0; i < 10; ++i)
x.add(i);
for(X::iterator it = x.begin(), ite = x.end(); it != ite; ++it)
std::cout << *it << ' ';
}
Live example at Ideone. Output:
0 2 4 6 8
This isn't a very nice solution, but I'll post it anyway. Any attempt to dereference this iterator wrapper will cause it to check the current value and advance the iterator past any negative values. It will be called recur
template<typename InputIterator>
struct nonnegative_iterator : InputIterator {
template<typename Arg>
nonnegative_iterator(Arg i) : InputIterator(i) {
}
typename InputIterator :: reference operator* () {
typename InputIterator :: reference x = InputIterator :: operator*();
if( x < 0) {
++ (*this); // equivalent to this -> operator++ ()
return **this;
} else
return x;
}
};
which can be used like this:
for ( nonnegative_iterator< vector<int>::iterator > it = v.begin(); it!=v.end(); ++it) {
This has some problems, for example I haven't implemented a const method to allow to dereference to value_type. So use at your own risk!
Assuming you don't have control over the interface of vector<int>, e.g. because it is actually std::vector<int>, the first thing you want to do is to change the way you get your custom iterators. That is, instead of writing
for (vector<int>::my_iterator it = v.my_begin(); it != v.my_ned(); ++it)
you would use
for (my_iterator it(my_begin(v)), end(my_end(v)); it != end; ++it)
You can achieve the modified interface for a custom container but this is a bigger fish to fry. Creating your input iterator now essentially amounts to creating a suitable wrapper for the underlying iterator. This could look something like this:
template <typename InIt, Pred>
struct my_iterator {
typedef typename std::iterator_traits<InIt>::value_type value_type;
typedef typename std::iterator_traits<InIt>::difference_type difference_type;
typedef typename std::iterator_traits<InIt>::reference reference;
typedef typename std::iterator_traits<InIt>::pointer pointer;
my_iterator(InIt it, InIt end, Pred pred): it_(it), end_(end), pred_(pred) {}
bool operator== (my_iterator const& other) const { reutrn this->it_ == other.it_; }
bool operator!= (my_iterator const& other) const { return !(*this == other); }
reference operator*() { return *this->it_; }
pointer operator->() { return this->it_; }
my_iterator& operator++() {
this->it_ = std::find_if(this->it_, this->end_, this->pred_);
return *this;
}
my_iterator operator++(int)
{ my_iterator rc(*this); this->operator++(); return rc; }
private:
InIt it_, end_;
Pred pred_;
The my_begin() and my_end() functions would then create a suitable object of this type. One approach to avoid having to write this is to have a look a Boost's iterator adaptors: there should be something suitable over there.
Related
Suppose I have a nested structure, say some class that contains some other classes:
struct Obj
{
std::vector<T> mVector; // T is large
};
std::vector<Obj> myVector;
I want to use some existing function, let's call it std::find_if, to find occurrences of T that match some criterion, etc. Many Standard Library functions (std::find_if included) require iterable ranges as inputs, so simply passing myVector iterators into these functions will cause the rows, not the elements, to be traversed.
Performance is also a concern so I don't want to have to reconstruct an entire vector of pointers or, worse, copy the objects themselves just in order to run these functions across the elements.
Having used boost::adaptors for various useful tasks such as filtering or indirecting containers without reconstructing them first, I figure I basically want to be able to do something like this:
auto myRange = boost::adaptors::nested(myVector, functor);
Where functor is some lambda that yanks nested ranges out of each row in my matrix, something like this:
auto functor = [](auto& it) { return boost::iterator_range(it.begin(), it.end(); }
Of course, boost::adaptors::nested doesn't exist. So how can I flatten this 2D array without copying Obj and without creating another flattened container first? The answer should be reasonably efficient while minimising the amount of code and boilerplate.
The answer is indeed to write an adaptor. It will need to keep track of the iterator in the outer container, and an iterator within the inner container.
Here is an example implementation, that only supports forward_iterator semantics, and const access — I'll leave a more complete implementation to you!
#include <cstddef>
#include <iterator>
template <typename V>
struct flat_view {
V &v;
typedef typename V::value_type inner_type;
typedef typename inner_type::value_type value_type;
typedef typename inner_type::reference reference;
typedef typename inner_type::const_reference const_reference;
struct const_iterator {
typedef std::forward_iterator_tag iterator_category;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::value_type value_type;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::pointer pointer;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::reference reference;
typedef ptrdiff_t difference_type;
typename inner_type::const_iterator i,i_end;
typename V::const_iterator o,o_end;
bool at_end;
const_iterator(): at_end(true) {}
const_iterator(typename V::const_iterator vb,typename V::const_iterator ve):
o(vb), o_end(ve), at_end(vb==ve)
{
if (!at_end) {
i=vb->begin();
i_end=vb->end();
}
}
const_iterator &operator++() {
if (at_end) return *this;
if (i!=i_end) ++i;
while (!at_end && i==i_end) {
if (++o==o_end)
at_end=true;
else {
i=o->begin();
i_end=o->end();
}
}
return *this;
}
const_iterator &operator++(int) {
iterator c(*this);
++*this;
return c;
}
bool operator==(const const_iterator &x) const {
return (at_end && x.at_end) || (o==x.o && i==x.i);
}
bool operator!=(const const_iterator &x) const { return !(*this==x); }
reference operator*() const { return *i; }
pointer operator->() const { return &*i; }
};
typedef const_iterator iterator;
explicit flat_view(V &v_): v(v_) {};
iterator begin() const { return iterator(v.begin(),v.end()); }
iterator end() const { return iterator(); }
const_iterator cbegin() const { return const_iterator(v.begin(),v.end()); }
const_iterator cend() const { return const_iterator(); }
};
template <typename V>
flat_view<V> make_flat_view(V &v) { return flat_view<V>(v); }
Quick demo:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<double>> v={
{1,2,3,4},
{},
{10,9,8,7},
{5,6}
};
auto f=make_flat_view(v);
std::copy(f.begin(),f.end(),std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
produces:
1 2 3 4 10 9 8 7 5 6
I have some templates which can either have a map or a vector as underlying container. I would like the template to be able to expose const iterators to the elements. Most information I have read on how to expose iterators (such as this accu article) uses a form of
typedef std::vector<int>::iterator iterator;
typedef std::vector<int>::const_iterator const_iterator;
iterator begin() { return values.begin(); }
iterator end() { return values.end(); }
That doesn't really work for the template that uses the map though, because to access elements, the template can't use it->SomeMemberFunc() anymore, but rather needs to use it->second.SomeMemberFunc(). So I am looking to expose an iterator to the map elements which doesn't give access to the keys but only the values of the map.
How would I accomplish this?
A workaround1
#include <map>
#include <iterator>
template <typename Iter>
struct map_iterator : public std::iterator<std::bidirectional_iterator_tag,
typename Iter::value_type::second_type>
{
map_iterator() {}
map_iterator(Iter j) : i(j) {}
map_iterator& operator++() { ++i; return *this; }
map_iterator& operator--() { --i; return *this; }
bool operator==(map_iterator j) const { return i == j.i; }
bool operator!=(map_iterator j) const { return !(*this == j); }
typename map_iterator::reference operator*() { return i->second; }
typename map_iterator::pointer operator->() { return &i->second; }
map_iterator operator--(int) { return std::prev(--(*this)); }
map_iterator operator++(int) { return std::next((++*this)); }
protected:
Iter i;
};
template <typename Iter>
inline map_iterator<Iter> make_map_iterator(Iter j) {
return map_iterator<Iter>(j);
}
And then
int main() {
std::map<int,std::string> m {{1, "Hi"},{2, "Bye"}};
for (auto i=make_map_iterator(m.begin()); i!=make_map_iterator(m.end());i++)
cout << *i << endl;
}
Live code.
I want to implement a cyclic list based on std::list. I want to profit from the benfits of the list but add one specific feature: its iterator operators ++ and -- should hop over the edges and operations (insert/erase) must not invalidate existing iterators. My skills in handling templates are weak and to understand the std containers is an impossible act for me. Hence i need your help. By now im not that far :D. Sorry but even the numerous posts dont help me any further.
EDIT:
Well after a lot of work, a steeeep learnig curve, the failed approach to inherit from std::list::iterator, a short-term depression and a abasing return to your approaches (yes, you all were right) I finally made it. Inspired by all your contibutions, I can now post what I did the last ... about 12 hours :D Basicly what you suggested, but with nice little operators.
#pragma once
#include <list>
using std::list;
template<class T>
class cyclic_iterator;
template<class T>
class cyclicList : public list<T>
{
public:
typedef cyclic_iterator<T> cyclic_iterator;
cyclic_iterator cycbegin()
{// not the purpose, but needed for instanziation
return cyclic_iterator( *this, this->begin());
}
cyclic_iterator cycend()
{// not the purpose, but needed for instanziation
return cyclic_iterator( *this, this->end());
}
};
template<class T>
class cyclic_iterator
{
public:
// To hop over edges need to know the container
cyclic_iterator(){}
cyclic_iterator(typename list<T>::iterator i)
: mIter(i){}
cyclic_iterator(list<T> &c)
: mContainer(&c){}
cyclic_iterator(list<T> &c, typename list<T>::iterator i)
: mContainer(&c), mIter(i){}
cyclic_iterator<T>& operator=(typename list<T>::iterator i)
{// assign an interator
mIter = i;
return *this;
}
cyclic_iterator<T>& operator=(list<T> &c)
{// assign a container
mContainer = &c;
return *this;
}
bool operator==(const cyclic_iterator<T>& rVal) const
{// check for equality
return (this->mIter == rVal.mIter && this->mContainer == rVal.mContainer) ? true : false;
}
bool operator!=(const cyclic_iterator<T>& rVal) const
{// check for inequality
return !(this->operator==(rVal));
}
cyclic_iterator<T>& operator++()
{// preincrement
++mIter;
if (mIter == mContainer->end())
{ mIter = mContainer->begin(); }
return *this;
}
cyclic_iterator<T> operator++(int)
{ // postincrement
cyclic_iterator<T> tmp = *this;
++*this;
return tmp;
}
cyclic_iterator<T>& operator--()
{// predecrement
if (mIter == mContainer->begin())
mIter = --mContainer->end();
else --mIter;
return *this;
}
cyclic_iterator<T> operator--(int)
{// postdecrement
cyclic_iterator<T> tmp = *this;
--*this;
return tmp;
}
cyclic_iterator<T>& operator+=(int j)
{// hop j nodes forward
for (int i = 0; i < j; ++i)
++(*this);
return *this;
}
cyclic_iterator<T>& operator-=(int j)
{// hop j nodes backwards
for (int i = 0; i < j; ++i)
--(*this);
return *this;
}
T& operator*()
{
return *mIter;
}
typename list<T>::iterator & getStdIterator()
{
return mIter;
}
private:
list<T>* mContainer;
typename list<T>::iterator mIter;
};
Can't you just make a different iterator type?
#include <iterator>
#include <list>
template <typename T, typename Alloc>
struct cyclic_iterator
: std::iterator<typename std::list<T, Alloc>::iterator::iterator_category, T>
{
typedef std::list<T, Alloc> list_type;
cyclic_iterator & operator++()
{
++iter;
if (iter == container.end()) { iter = container.begin(); }
return *this;
}
T & operator*() { return *iter; }
cyclic_iterator(typename list_type::iterator it, list_type & l)
: iter(it)
, container(l)
{
if (it == container.end()) { it = container.begin(); }
}
// everything else
private:
typename list_type::iterator iter;
list_type & container;
};
With a helper:
template <typename List>
cyclic_iterator<typename List::value_type, typename List::allocator_type>
make_cyclic_iterator(typename List::iterator it, List & l)
{
return cyclic_iterator<typename List::value_type, typename List::allocator_type>(it, l);
}
Usage:
// goes round and round forever
for (auto ci = make_cyclic_iterator(mylist.begin(), mylist); ; ++ci)
{
std::cout << *ci << std::endl;
}
(With a few modifications, this code could be made to work on any container that exposes begin/end iterators.)
It's not possible. The iterators and the implementation of the end element is implementation specific and not customizable. Containers were not designed for that kind of thing and it would make them really hard. You will have to go through the pain of implementing this yourself. Keep in mind that this gets very tricky because a cyclic list doesn't have a real past-the-end iterator and iterators aren't really able to handle that kind of situation. Some libraries have a Circulator concept to deal with circular structures.
NB: Inheriting from a standard container is a bad idea.
Of course you can implement it using std::list, but first you should encapsulate list in your class and do not derive from it second you must implement your own iterator to accomplish this, but since circular lists are fixed in size I prefer a container with a fixed size and linear memory like std::array or std::vector.
template<
class T,
class Container = std::vector<T>
>
class circular_list {
public:
// Following typedef are required to make your class a container
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
typedef typename Container::pointer pointer;
typedef typename Container::const_pointer const_pointer;
typedef typename Container::reference reference;
typedef typename Container::const_reference const_reference;
typedef typename Container::value_type value_type;
public:
class iterator : std::iterator<std::bidirectional_iterator_tag, value_type> {
public:
iterator() : c_(nullptr) {}
iterator(circular_buffer& c, size_type index)
: c_( &c.c_ ), index_( index ) {}
reference operator* () const {
return (*c_)[index_];
}
iterator& operator++ () {
if( ++index_ >= c_->size() ) index_ = 0;
return *this;
}
iterator& operator-- () {
if( index_ == 0 ) index_ = c_->size() - 1; else --index_;
return *this;
}
private:
size_type index_;
Container* c_;
};
public:
void push( const_reference val ) {add item to the container}
reference current() {return current item from the container}
void pop() {remove item from the container}
size_type size() const {return c_.size();}
iterator begin() {return iterator( *this, 0 );}
iterator end() {return iterator( *this, size() );}
private:
friend iterator;
Container c_;
}
When I have a template class which contains template map and a const_iterator declared as in the following code by typedef, how can I iterate through the elements of the map outside the class, f.e in main to print them on the output?
template<class K, class V>
class template_map{
private:
typedef typename std::map<K,V> TMap;
TMap my_map;
public:
typedef typename TMap::const_iterator const_iterator;
...
};
int main()
{
template_Map<int,double> Map1 //suppose that contains elements
?
}
Update: Can the typedef iterator be used outside the class? If yes in what way?
You need to define member functions on your template that would return iterators:
template<class K, class V>
class template_map{
private:
typedef typename std::map<K,V> TMap;
TMap my_map;
public:
typedef typename TMap::const_iterator const_iterator;
const_iterator begin() const { return my_map.begin(); }
const_iterator end() const { return my_map.end(); }
};
Then:
int main()
{
template_map<int, int> m;
// Populate map...
// Then iterate...
for (auto i = m.begin(); i != m.end(); i++)
{
}
}
However, I am unsure what your adding to std::map here, why not just use it as is?
Add begin() and end() members to template_Map (both const and non-const variants).
const_iterator begin() const {
return my_map.begin();
}
const_iterator end() const {
return my_map.end();
}
iterator begin() {
return my_map.begin();
}
iterator end() {
return my_map.end();
}
I added non-const versions just for interface completeness, it may not be required in your case.
Than in main:
typedef template_Map<x, y> template_MapXY;
template_MapXY Map1;
...
for ( template_MapXY::const_iterator it( Map1.begin() ), end( Map1.end() ); it != end; ++ it ) {
...
}
I don't understand why you want to wrap a map class with another one. Why don't you std::map itself?
Iteration over a std::map is usually done like this:
for(std::map<mykey, myvalue>::iterator it = mymap.begin(); it != mymap.end(); ++it)
{
somevar = it->first; // <<--- points to your key
someothervar = it->second; // points to your value
}
I need to find the indexes in the vector based on several boolean predicates.
ex:
vector<float> v;
vector<int> idx;
idx=where( bool_func1(v), bool_func2(v), ... );
What is the way to declare **where** function, in order to use the several user defined boolean functions over the vector?
thanks
Arman.
Edit after one week
I did some complex solutions with templates. But in reality one can use already predefined valarray for my tasks. Here is the code snippet maybe one can find it useful:
double dr=Rc/(double)Nbins, r;
sigma.resize(Nbins);
rr=sigma;
valarray<double> vz(&data.vz[0], data.vz.size());
double mvel=vz.sum()/(double)vz.size();
for(size_t i=0l;i<Nbins;i++)
{
r=dr*i;
valarray<bool> ids = (dist < r+dr) && (dist > r);//The magic valarray<bool>
if(ids.max())
{
valarray<double> d=vz[ids];//we can use indirect operation.
d-=mvel;
d=pow(d,2.0);
sigma[i]= sqrt(d.sum()/(double)d.size());
rr[i]=r;
cout<<i<<") "<<r<<" "<<sigma[i]<<endl;
}
}
Make your bool_xxx functions actually functors of a specific kind of type (tag dispatching would be enough). Then override || and && for them such that these operators return a bool_and, or bool_or. Then you can use your bool_ predicates like so:
std::find_if(vect.begin(), vect.end(), bool_x1() || bool_x2() && (bool_x3() || bool_x4() && bool_x5()));
If you're tempted to write a "where" function then you apparently want to do this more than once with a different set of bool_xxx functions. Even if you know that you want a certain type of composition now, you may as well make it as universal as possible. This is how I'd do it.
Edit:
Based on this comment: #Jerry: For example I need to know: id=where(v < 10.0 && v>1.0); and somewhere later I would like to know: id=where(v < fun(v)); you may be better off with boost::lambda:
namespace l = boost::lambda;
std::find_if(vect.begin(), vect.end(), l::_1 < 10.0 && l::_1 > 1.0);
std::find_if(vect.begin(), vect.end(), l::_1 < l::bind(fun, l::_1));
Or, if you hate lambda or aren't allowed to use it...or just want a very slightly nicer syntax (but inability to use functions directly) then just make your own placeholder type and override it to return bool_xxx functors on operators <, >, etc...
Edit2: Here's an untested where that returns a vector of iterators to all objects matching:
template < typename ForwardIter, typename Predicate >
std::vector<ForwardIter> where(ForwardIter beg, ForwardIter end, Predicate pred)
{
ForwardIter fit = std::find_if(beg,end,pred);
if (fit == end) return std::vector<ForwardIter>();
ForwardIter nit = fit; ++nit;
std::vector<ForwardIter> collection = where(nit,end,pred);
collection.push_front(fit);
return collection;
}
It's recursive and could be slow on some implementations but there's one way to do it.
You could use a predicated version of transform, if there were one. There's not one, but it is very easy to write:
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
OutputIterator transform_if(InputIterator first,
InputIterator last,
OutputIterator result,
UnaryFunction f,
Predicate pred)
{
for (; first != last; ++first)
{
if( pred(*first) )
*result++ = f(*first);
}
return result;
}
Then you would need a way to make a composite of multiple predicates, so that you could express something like find_if( begin, end, condition1 && condition2 ). This, again, is easy to write:
template<typename LHS, typename RHS> struct binary_composite : public std::unary_function<Gizmo, bool>
{
binary_composite(const LHS& lhs, const RHS& rhs) : lhs_(&lhs), rhs_(&rhs) {};
bool operator()(const Gizmo& g) const
{
return lhs_->operator()(g) && rhs_->operator()(g);
}
private:
const LHS* lhs_;
const RHS* rhs_;
};
Finally you need a gizmo that transform_if uses to convert an object reference to an object pointer. Surprise, surprise, easy to write...
template<typename Obj> struct get_ptr : public std::unary_function<Obj, Obj*>
{
Obj* operator()(Obj& rhs) const { return &rhs; }
};
Let's put this all together with a concrete example. Gizmo below is the object that you have a collection of. We have 2 predicates find_letter and find_value that we want to search for matches to in our main vector. transform_if is the predicated version of transform, get_ptr converts an object reference to a pointer, and binary_composite strings together the two composites.
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>
using namespace std;
struct Gizmo
{
string name_;
int value_;
};
struct find_letter : public std::unary_function<Gizmo, bool>
{
find_letter(char c) : c_(c) {}
bool operator()(const Gizmo& rhs) const { return rhs.name_[0] == c_; }
private:
char c_;
};
struct find_value : public std::unary_function<Gizmo, int>
{
find_value(int v) : v_(v) {};
bool operator()(const Gizmo& rhs) const { return rhs.value_ == v_; }
private:
int v_;
};
template<typename LHS, typename RHS> struct binary_composite : public std::unary_function<Gizmo, bool>
{
binary_composite(const LHS& lhs, const RHS& rhs) : lhs_(&lhs), rhs_(&rhs) {};
bool operator()(const Gizmo& g) const
{
return lhs_->operator()(g) && rhs_->operator()(g);
}
private:
const LHS* lhs_;
const RHS* rhs_;
};
template<typename LHS, typename RHS> binary_composite<LHS,RHS> make_binary_composite(const LHS& lhs, const RHS& rhs)
{
return binary_composite<LHS, RHS>(lhs, rhs);
}
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
OutputIterator transform_if(InputIterator first,
InputIterator last,
OutputIterator result,
UnaryFunction f,
Predicate pred)
{
for (; first != last; ++first)
{
if( pred(*first) )
*result++ = f(*first);
}
return result;
}
template<typename Obj> struct get_ptr : public std::unary_function<Obj, Obj*>
{
Obj* operator()(Obj& rhs) const { return &rhs; }
};
int main()
{
typedef vector<Gizmo> Gizmos;
Gizmos gizmos;
// ... fill the gizmo vector
typedef vector<Gizmo*> Found;
Found found;
transform_if(gizmos.begin(), gizmos.end(), back_inserter(found), get_ptr<Gizmo>(), binary_composite<find_value,find_letter>(find_value(42), find_letter('a')));
return 0;
}
EDIT:
Based on sbi's iterative approach, here's a predicated version of copy, which is more in line with the general STL paradigm, and can be used with back_insert_iterator to accomplish what's wanted in this case. It will give you a vector of object, not iterators or indexes, so the transform_if I posted above is still better for this use than copy_if. But here it is...
template<class InputIterator, class OutputIterator, class Predicate>
OutputIterator copy_if(InputIterator first,
InputIterator last,
OutputIterator result,
Predicate pred)
{
for (; first != last; ++first)
{
if( pred(*first) )
*result++ = *first;
}
return result;
}
This seems like a problem that could much easier be solved in an declarative language like Prolog. I gave it a try in C++ anyway:
typedef float type;
typedef bool (*check)(type);
std::vector<int> where(const std::vector<type>& vec,
const std::vector<check>& checks)
{
std::vector<int> ret;
for (int i = 0; i < vec.size(); i++)
{
bool allGood = true;
for (int j = 0; j < checks.size(); j++)
{
if (!checks[j](vec[i]))
{
allGood = false;
break;
}
}
if (allGood)
ret.push_back(i);
}
return ret;
}
I am not sure which indexes you want. Is this what you are trying to acheive:
//Function pointer declaration
typedef bool (*Predicate)(const std::vector<float>& v);
//Predicates
bool bool_func1(const std::vector<float>& v)
{
//Implement
return true;
}
bool bool_func2(const std::vector<float>& v)
{
//Implement
return true;
}
std::vector<int> where_func(const std::vector<float>& v,
const std::vector<Predicate>& preds)
{
std::vector<int> idxs;
std::vector<Predicate>::const_iterator iter = preds.begin();
std::vector<Predicate>::const_iterator eiter = preds.end();
for(; iter != eiter; ++iter)
{
if((*iter)(v))
{
idxs.push_back(eiter - iter);
}
}
return idxs;
}
template<typename Vector, typename T> std::vector<int> where(const std::vector<Vector>& vec, T t) {
std::vector<int> results;
for(int i = 0; i < vec.size(); i++) {
if (t(vec[i])
results.push_back(i)
}
return results;
}
Overload for additional function object arguments as you wish. Use:
template<typename T> struct AlwaysAccept {
bool operator()(const T& t) { return true; }
};
std::vector<float> floats;
// insert values into floats here
std::vector<int> results = where(floats, AlwaysAccept<float>());
Noah Robert's solution is nice, but I'm not wholly sure how I could make that work.