I am getting a lot of errors trying to use an iterator for three dimensional vector of sets of ints. See the following code (which is just select pieces, because the whole thing is too long; I think this should be enough to see what is wrong, but let me know if it isn't):
vector<vector<vector<set<int> > > > particles_celllist;
vector<vector<vector<set<int> > > >::iterator cell_iter;
map<int,map<int,Particle> > particle_grid;
for (cell_iter=particles_celllist[wx][wy][wz].begin();cell_iter!=particles_celllist[wx][wy][wz].end();cell_iter++)
{
double distance_to_cell=sqrt(pow(particles[*cell_iter].position().y()-(wy)*ygridlength,2)+
pow(particles[*cell_iter].position().z()-(wz)*zgridlength,2));
if (distance_to_cell<input_data.diam_large())
{
particle_grid[box_counter][*cell_iter]=particles[*cell_iter];
}
}
Note: wx, wy, wz, and box_counter are ints, ygridlength and zgridlength are doubles, and Particle::position::y (or ::z) and input_data::diam_large return doubles.
I get a multitude of errors:
no match for operator "=" in
"cell_iter=particles_celllist[wx][wy][wz].begin()"
no match for operator "!=" in
"cell_iter!=particles_celllist[wx][wy][wz].end()"
no match for operator "[]" whenever I used [*cell_iter] to call
something
I get the feeling like the error somehow stems from the iterator itself, but I haven't been able to figure it out.
You want set<int>::iterator cell_iter;. Just look again carefully at whose begin() function you're calling.
In C++11 you would of course just have said
auto cell_iter = particles_celllist[wx][wy][wz].begin()
and never noticed that this is hard :-)
particles_celllist[wx][wy][wz] is of type set<int>, so particles_celllist[wx][wy][wz].begin() is of type set<int>::iterator
Related
I'm new to C++ STL. I'm writing a function to check whether one vector is an subset of another(Duplicate elements also count) and print 'Yes' or 'No'. I have come up with the following code :
void checkMagazine(vector<string> magazine, vector<string> note) {
vector<string>::iterator a;
for(int i=0;i<note.size();i++)
{
a=find(magazine.begin(),magazine.end(),note[i]);
if(a==magazine.end())
{
printf("No");
return;
}else magazine.erase(a-magazine.begin());
}
printf("Yes");
}
But,I'm getting the following compilation error :
error: no matching function for call to ‘std::vector<std::__cxx11::basic_string<char>
>::erase(__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*,
std::vector<std::__cxx11::basic_string<char> > >::difference_type)’
}else magazine.erase(a-magazine.begin());
I'm trying to use erase to delete the found element in magazine.Is there some problem with the type of declaration of the iterator? Why is this happening?
And also if there are alternate methods/logic/inbuilt-functions to get the required job done using STL, Please let me know since I'm new to this and trying to learn it.
erase takes an iterator. You have that iterator, it's called a. But you then convert the iterator a into an offset relative to begin(). erase does not have an overload which takes an offset.
The Standard Library has alternatives if the vectors would be sorted, but we don't see the calling code so we can't assume that.
my function tries to find if an element already exists in a vector of a class objects pointers
I kind of understand the source of the problem but I can't seem to find a solution without having the implement a method for the == operation ,
the method in the cpp file :
bool Annuaire::PersonneEstDejaPresente(const Personne& p_personne) const{
vector<Personne*>::const_iterator iter;
iter = std::find(m_vMembres.begin(), m_vMembres.end(), p_personne);
return true;
//the return here is just for the sake of testing
}
the vector defined in the header file private part :
std::vector<Personne*> m_vMembres;
the error I get from the compiler is in the title,
I would be really apreciate any help.
The problem is that have an vector of pointers but what you are looking for is not a pointer.
This would compile
iter = std::find(m_vMembres.begin(), m_vMembres.end(), &p_personne);
but this will compare pointers not Personne objects. I guess that you really want to compare persons, so you might be better off using std::find_if instead of std::find.
The other thing you should consider is using vector<Personne> instead of vector<Personne*>. Do you have a good reason to use pointers in the first place?
I have two lists and a name to find. If the name to find is not in the first list then it might be in the second list with a slightly different format. Conversion function between the two formats are given.
std::map<CString, CString>* convertedNames;
BOOL CSome::SeekNameWithConversion(std::set<CString> names, CString nameToFind)
{
for (auto it = names.begin(); it != names.end(); ++it)
{
if (nameToFind.Compare(*it) == 0) return true;
auto convertedIt = convertedNames->find(*it);
if (convertedIt != convertedNames->end() &&
nameToFind.Compare(convertedIt->second) == 0)
return true;
CString justConvertedName = ConvertToTheOtherFormat(nameToFind);
convertedNames->insert(*it, justConvertedName); // Error here
return nameToFind.Compare(justConvertedName) == 0;
}
}
The error which appears is:
error C2675: unary '++':
'ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<_CharType>>>' does
not define this operator or a conversion to a type acceptable to the
predefined operator
I would like to know why the operator ++ is involved here and then how should I treat this error.
Most of the various insert functions of std::map require an iterator. Instead, you pass the pointed-to-object, (which is a CString, I suppose):
convertedNames->insert(*it, justConvertedName);
^^^
this is a CString, not a std::map<CString,CString>::iterator
If you want to insert a key-value pair, use the map's value_type instead which is basically a std::pair made up of key and value:
convertedNames->insert(std::make_pair(*it, justConvertedName));
The first argument to map::insert is an iterator, not a CString. Internally, the method is trying to increment the iterator. This apparently makes a call to operator++. You don't need to use this insert overload. It's intended to improve performance when you know a position close to where the element will be inserted. Just call convertedNames->insert(std::make_pair(*it, justConvertedName)) instead.
So the first thing to understand is that templates are always fully implemented in the header, as any classes required are built with that object (just think if the std lib had all possible std::vector implementations built in!)
This means that the implementation of the template is exposed - and in this case, there's a ++ somewhere there. If you take the whole error printed (it'll be quite a few more lines) you may even be told which parameter you've got wrong.
In any case, we can see that *it is clearly going to be a CString, but I'd guess that this
... convert to the other format
is probably not returning what you think
I'm trying to iterate over a boost::fusion vector using:
typedef typename fusion::result_of::begin<T>::type t_iter;
std::cout << distance(begin(t), end(t)) << std::endl;
for(t_iter it = begin(t); it != end(t); next(it)){
std::cout<<deref(it)<<std::endl;
}
The distance cout statement gives me a finite length (2), however the loop seems to run indefinitely.
Any advice much appreciated!
You can't just iterate a Fusion vector like that, the type for each iterator may be different than the previous one (and usually is). I guess that's why you don't have it = next(it) in your code, it would give a compilation error.
You could use boost::fusion::for_each for this, together with a function object that prints each element to the standard output:
struct print
{
template< typename T >
void operator()( T& v ) const
{
std::cout << v;
}
};
...
boost::fusion::for_each( t, print() );
fusion is a wonderful library, and you should now that it is really different from what you use in every day C++ programs in multiple ways, it merge the power of compile time meta programming with runtime, for that you should now that there is no type that can handle all items in a fusion container. What this means? it means that result_of::begin<T>::type is not always a match of next(it) so you can't use fusion iterators in a for like that.
The obvious problem in your code is that you ignore return value of next and it will cause your code to run forever but you can't use it in it = next(it), since their type may vary!!
So what you should do?? You should use boost::fusion::for_each for that purpose
next doesn't actually advance the iterator, it just returns the next one.
This can be seen in the docs, as the function next takes a constant argument, meaning it can't possibly actually modify the iterator:
template<
typename I
>
typename result_of::next<I>::type next(I const& i);
^^^^^
The problem is that inside the loop you are dereferencing your iterator. When you apply next on it, it means nothing and that's why your loop runs forever.
I have a sequence of values that I'd like to pass to a function that takes a (iterator begin, iterator end) pair. However, I only want every second element in the original sequence to be processed.
Is there a nice way using Standard-Lib/Boost to create an iterator facade that will allow me to pass in the original sequence? I figured something simple like this would already be in the boost iterators or range libraries, but I didn't find anything.
Or am I missing another completely obvious way to do this? Of course, I know I always have the option of copying the values to another sequence, but that's not what I want to do.
Edit: I know about filter_iterator, but that filters on values - it doesn't change the way the iteration advances.
I think you want boost::adaptors::strided
struct TrueOnEven {
template< typename T >
bool operator()(const T&) { return mCount++ % 2 == 0; }
TrueOnEven() : mCount(0) {}
private:
int mCount;
};
int main() {
std::vector< int > tVec, tOtherVec;
...
typedef boost::filter_iterator< TrueOnEven, int > TakeEvenFilterType;
std::copy(
TakeEvenFilterType(tVec.begin(), tVec.end()),
TakeEvenFilterType(tVec.end(), tVec.end()),
std::back_inserter(tOtherVec));
}
To be honest, this is anything else than nice and intuitive. I wrote a simple "Enumerator" library including lazy integrated queries to avoid hotchpotch like the above. It allows you to write:
Query::From(tVec.begin(), tVec.end())
.Skip<2>()
.ToStlSequence(std::back_inserter(tOtherVec));
where Skip<2> basically instantiates a generalized "Filter" which skips every N-th (in this case every second) element.
Here's Boost's filter iterator. It is exactly what you want.
UPDATE: Sorry, read wrongly-ish. Here's a list of all iterator funkiness in Boost:
http://www.boost.org/doc/libs/1_46_1/libs/iterator/doc/#specialized-adaptors
I think a plain iterator_adaptor with an overloaded operator++ that increments the underlying iterator value twice is all you need.