How to enumerate a BOOST_ENUM with BOOST_FOREACH? - c++

Can somebody please explain me how to enumerate a BOOST_ENUM using BOOST_FOREACH ?
The example below show that I got it to work with std::for_each, but not with BOOST_FOREACH.
Sample code :
BOOST_ENUM_VALUES( MyEnum,
const char *,
(xMin)("xMin")
(xMax)("xMax")
(yMin)("yMin")
(yMax)("yMax")
);
void blah(const MyEnum & val) // working demo with std_foreach
{
std::cout << "index=" << val.index() << " val=" << val.value() << " str=" << val.str() << std::endl;
}
void foo()
{
//BOOST_FOREACH : does not compile...
BOOST_FOREACH(MyEnum myEnum, MyEnum() ) // I tried to construct a "dummy" enum in order to use its iterator with no luck...
{
std::cout << "index=" << myEnum.index() << " val=" << myEnum.value() << " str=" << myEnum.str() << std::endl;
}
//std::for_each : works...
std::for_each(MyEnum::begin(), MyEnum::end(), blah);
}
Many thanks in advance!
Edit: as mentioned in the answer, the code does work with the newest codebase of boost.

Your example code above compiles and runs just fine for me with gcc 4.5.1 and vc2010 (after adding the corresponding #include's, that is). I tried with enum_rev4.6 from the vault. What compilation errors do you see?

Related

Convert CV::Mat To Arma::mat

I try to convert form matrix in Opencv to matrix in armadillo
I found this func in this link
but when I try to call it give me error :
error C2783: 'arma::Mat cvMat2armaMat(cv::Mat &)' : could not deduce template argument for 'T3'
IntelliSense: no instance of function template "cvMat2armaMat" matches the argument list
This is function :
template<class T3>
arma::Mat <T3> cvMat2armaMat(cv::Mat & cvMatIn)
{
return armaConv (cvMatIn.data, cvMatIn.rows, cvMatIn.cols,false);
}
This is function calling ( the error appear when I call func )
cv::Mat CurrentImage = imread(path, 0);
arma::mat singleImage = cvMat2armaMat (CurrentImage);
what should I do ?
You need to specify the type of arma::mat<XXX> that cvMat2armaMat() returns.
What is armaConv?
Maybe you meant this:
template<class T3>
arma::Mat <T3> cvMat2armaMat(cv::Mat & cvMatIn)
{
return arma::Mat <T3> (cvMatIn.data, cvMatIn.rows, cvMatIn.cols,false);
}
and the call is this:
auto singleImage = cvMat2armaMat<float>(CurrentImage);
or you'll need to switch on the cv::Mat type.
I can answer how to do this on VC10 and g++ but I still have a few issues to be resolved. I am new to writing templated functions. It is often necessary to convert between cv::Mat and arma::mat matrix objects since Armadillo has more complete Linear Algebra facilities. OpenCV stores it's matrices in row-major order while Armadillo stores it's matrices in column-major order which is one component of this problem. I have created the following templated functions that have been tested in VC10 and g++ 4.9 to work on both float and double type matrices:
template<typename T>
static void Cv_mat_to_arma_mat(const cv::Mat_<T>& cv_mat_in, arma::Mat<T>& arma_mat_out)
{
cv::Mat_<T> temp(cv_mat_in.t()); //todo any way to not create a temporary?
#if defined(WIN32)
//This compiles on VC10 but not g++ 4.9 (on Debian with OpenCV 2.4.9.1 and Arma 4.320.0)
arma_mat_out = arma::Mat<T>(temp.ptr<T>(), //<<"error: expected primary-expression before '(' token"
static_cast<arma::uword>(temp.cols),
static_cast<arma::uword>(temp.rows),
true,
true);
#elif defined(LINUX)
//This compiles on both but is not as nice
arma_mat_out = arma::Mat<T>(reinterpret_cast<T*>(temp.data),
static_cast<arma::uword>(temp.cols),
static_cast<arma::uword>(temp.rows),
true,
true);
#endif
};
//This one is fine on both
template<typename T>
static void Arma_mat_to_cv_mat(const arma::Mat<T>& arma_mat_in,cv::Mat_<T>& cv_mat_out)
{
cv::transpose(cv::Mat_<T>(static_cast<int>(arma_mat_in.n_cols),
static_cast<int>(arma_mat_in.n_rows),
const_cast<T*>(arma_mat_in.memptr())),
cv_mat_out);
};
This code can be run with:
std::cout << "Testing arma::mat<->cv::Mat <double>:" << std::endl;
{
arma::Mat<double> A(3,2);
A << 1 << 2 << arma::endr
<< 3 << 4 << arma::endr
<< 5 << 6 << arma::endr;
cv::Mat_<double> cv_A(3,2);
M_math::Arma_mat_to_cv_mat<double>(A, cv_A);
std::cout << "Arma_mat_to_cv_mat<double>" << std::endl;
std::cout << A << std::endl;
std::cout << cv_A << std::endl;
std::cout << "Cv_mat_to_arma_mat<double>" << std::endl;
M_math::Cv_mat_to_arma_mat<double>(cv_A, A);
std::cout << cv_A << std::endl;
std::cout << A << std::endl;
}
std::cout << "Now <float>" << std::endl;
{
arma::Mat<float> A(3,2);
A << 1 << 2 << arma::endr
<< 3 << 4 << arma::endr
<< 5 << 6 << arma::endr;
cv::Mat_<float> cv_A(3,2);
M_math::Arma_mat_to_cv_mat<float>(A, cv_A);
std::cout << "Arma_mat_to_cv_mat<float>" << std::endl;
std::cout << A << std::endl;
std::cout << cv_A << std::endl;
std::cout << "Cv_mat_to_arma_mat<float>" << std::endl;
M_math::Cv_mat_to_arma_mat<float>(cv_A, A);
std::cout << cv_A << std::endl;
std::cout << A << std::endl;
}
My further questions are:
Any idea what I am doing wrong? This seems like it is a case of VC10 being more permissive than g++ but what am I missing if I want to keep using the first (nicer) version with g++?
In Cv_mat_to_arma_mat(...) are there any suggestions to get around the row-major order vs row-order issue without creating a temporary? cv_mat_in.t() does not alter the internal memory pointer in cv_mat_in, it is just a cv::MatExpr.
Any criticism of the style, safety, or performance of these functions would be appreciated. Of course they will not work with cv::Mat's that have more than one channel.

how to iterate through boost unordered_map?

I just want to iterate through the members of an unordered map.
There are many simple examples on the web, including on this site, and yet none of them will compile. Apparently some examples are from a previous non-standard STL version, some are just old, and some are so new that my gcc 4.7.2 can't handle them. Please do not suggest the new auto iterator from C++11. I will get there some day when all my libraries are validated for that. Until then, I just want the old one to work. (see below for what I have tried)
Here is my test code:
#include <iostream>
#include <boost/unordered_map.hpp>
#include <string>
int main(int argc,char *argv[]) {
boost::unordered::unordered_map<std::string,int> umap;
//can't get gcc to accept the value_type()...
//umap.insert(boost::unordered_map::value_type("alpha",1));
//umap.insert(boost::unordered_map::value_type("beta",2));
//umap.insert(boost::unordered_map::value_type("gamma",3));
umap["alpha"]=1; //this works
umap["beta"]=2;
umap["gamma"]=3;
//can't get gcc to compile the iterator
//for (boost::unordered_map::iterator it=umap.begin();it!=umap.end();++it)
// std::cout << it->first <<", " << it->second << std::endl;
//gcc does not like it this way either
//for (int x=0;x<umap.size();x++)
// std::cout << x << " : " << umap[x].first << " = " << umap[x].second << std::endl;
//will gcc take this? No it does not
//for (int x=0;x<umap.size();x++)
// std::cout << x << " : " << umap[x] << std::endl;
//this does not work
//boost::unordered::unordered_map::iterator<std::string,int> it;
//this does not work
//boost::unordered::unordered_map::iterator it;
//for (it=umap.begin();it!=umap.end();++it)
// std::cout << it->first <<", " << it->second << std::endl;
//this does not work
//BOOST_FOREACH(boost::unordered_map::value_type value, umap) {
// std::cout << value.second;
// }
//std::cout << std::endl;
//this does not work either
//BOOST_FOREACH(boost::unordered_map::value_type<std::string,int> value, umap) {
// std::cout << value.second;
// }
//std::cout << std::endl;
std::cout << "umap size: " << umap.size() << std::endl;
std::cout << "umap max size: " << umap.max_size() << std::endl;
std::cout << "find alpha: " << (umap.find("alpha")!=umap.end()) << std::endl;
std::cout << "count beta: " << umap.count("beta") << std::endl;
}
Most of the errors are a variation of this:
error: 'template<class K, class T, class H, class P, class A> class boost::unordered::unordered_map' used without template parameters
Here is my build command:
g++ -I..\boost umap.cpp
I should be embarrassed for getting stuck on such a beginner's question, but from the volume of similar questions I am finding, this is just hard enough to stop a lot of people in their tracks. I have written hash containers before (back when it was recommended NOT to use STL) and I am very tempted to just write my own... but the right thing to do is learn to use as many existing tools as possible... help!
I've looked at the following questions on stackoverflow where I haven't found an answer:
iterate through unordered_map using boost_foreach
I tried:
BOOST_FOREACH(boost::unordered_map::value_type& value, umap) {
but it gives the same error I show below.
Unordered_map iterator invalidation
This one is close, but not quite my issue:
Iterator invalidation in boost::unordered_map
This one uses auto
and I can't switch compilers at this time.
C++ some questions on boost::unordered_map & boost::hash
This one is mostly about the theory of maps:
how to use boost::unordered_map
This is a rather complicated example, but you will see in my code I am already trying to declare iterators... they just won't compile.
How to use BOOST_FOREACH with an Unordered_map?
This is a nice example, but
it just does not compile. I tried a version of this in my code.
IT WORKS !
Here is the working code:
#include <iostream>
#include <boost/unordered_map.hpp>
#include <string>
int main(int argc,char *argv[]) {
boost::unordered::unordered_map<std::string,int> umap;
umap["alpha"]=1;
umap["beta"]=2;
umap["gamma"]=3;
boost::unordered::unordered_map<std::string,int>::iterator it;
for (it=umap.begin();it!=umap.end();++it)
std::cout << it->first <<", " << it->second << std::endl;
std::cout << "umap size: " << umap.size() << std::endl;
std::cout << "umap max size: " << umap.max_size() << std::endl;
std::cout << "find alpha: " << (umap.find("alpha")!=umap.end()) << std::endl;
std::cout << "count beta: " << umap.count("beta") << std::endl;
}
It was a syntax error. I was putting the type in the wrong place when declaring the iterator.
Thanks everyone for your responses.
try changing boost::unordered::unordered_map::iterator it; it to boost::unordered::unordered_map<std::string,int>::iterator it;
NOTE:
It is also possible, and a good idea in more complex situations, to create a typedef of it, such as typedef boost::unordered::unordered_map<std::string,int>::iterator UMapStringIntIt;, or whatever you may call it.
The answer is in the question, but the simple solution is here for your convenience:
#include <iostream>
#include <boost/unordered_map.hpp>
#include <string>
int main(int argc,char *argv[])
{
boost::unordered::unordered_map<std::string,int> umap;
umap["alpha"]=1;
umap["beta"]=2;
umap["gamma"]=3;
for ( auto it= umap.begin(); it != umap.end(); ++it )
std::cout << it->first <<", " << it->second << std::endl;
}

Differences between std::set and boost::ptr_set?

I've changed some code to convert a std::set to a boost::ptr_set. However, the code doesn't compile; the problem is that I'm assuming that the return value from a ptr_set insert is the same as a set insert (a pair<myIter, bool>). After an hour on Google I found this, and it turns out that the return value from a ptr_set insert appears to be a bool.
Is there any definitive documentation on the differences between the ptr containers and the std containers? I haven't found anything on the boost website, but maybe I'm just being dumb...
EDIT
Ok - what was confusing me was that this code
t.insert(s.release(s.begin()));
p = t.insert(s.release(s.begin()));
reports no error on the first line on gcc, but reports no match for operator= on the second line, so I thought the error was in the return type. However, if you comment out the second line, the first line is then reported as an error (release doesn't return an iterator). My confusion was compounded by the link I posted, in which ptr_container's author states that "insert() in ptr_set<> returns bool". However, reading on down the link it becomes obvious that the code hadn't been finished at the time. Thanks Kerrek.
The following code works as expected, and the interface is the same as for std::set::insert():
#include <boost/ptr_container/ptr_set.hpp>
#include <boost/assign/ptr_list_inserter.hpp>
#include <iostream>
int main()
{
boost::ptr_set<int> s;
{
auto p = s.insert(new int(4));
std::cout << "Element " << *p.first << (p.second ? " inserted" : " already existed") << std::endl;
}
{
auto p = s.insert(new int(4));
std::cout << "Element " << *p.first << (p.second ? " inserted" : " already existed") << std::endl;
}
boost::assign::ptr_insert(s)(1)(2)(3)(4);
for (auto it = s.begin(), end = s.end(); it != end; ++it) { std::cout << *it << "\n"; }
}
The documentation is perhaps not the easiest to navigate, but it's all there. You should look for the "set adapter", though, perhaps that's not entirely obvious.

C++ STL map with custom comparator storing null pointers

I'm trying to write a copy constructor for an object managing a STL map containing pointers, where the key is a string. However, when I attempt to insert new values in the map, the pointers are set to NULL:
// ...
for(std::map<std::string, data_base*, order>::const_iterator it = other.elements.begin();
it != other.elements.end(); ++it){
data_base *t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
elements[it->first] = t;
std::cout << "INSERTED: " << std::hex << elements[it->first] << std::endl;
}
// ...
other is the object being copied and elements the map. The clone() method returns a pointer to a new object (via new).
Running the code above I get something like:
CLONE: 0xcfbbc0
INSERTED: 0
I'm not a very experienced programmer and this issue is probably simple to fix, but I didnt find any solution to it searching around.
Thanks a lot for your time.
I don't see any problem with this code, other than maybe
std::map<std::string, data_base*, order>::const_iterator it
Here order gives the key comparator to use to sort the pairs contained in the map (often implemented as a tree).
Maybe you're doing something wrong in it, making your [] operator don't find the right ke, making your last line logging a new pair with a null ptr.
First, try without that order, using the default key-comparator (std::less), then if it don't work, post your order definition and the map declaration. If it's not enough, just provide a simple complete program that reproduce the problem.
I just wrote a simple similar test, using the default key-comparator :
#include <map>
#include <string>
#include <iostream>
struct Data
{
int k;
Data* clone() { return new Data(); }
};
typedef std::map< std::string, Data* > DataMap;
DataMap data_map;
int main()
{
data_map[ "hello" ] = new Data();
data_map[ "world" ] = new Data();
DataMap other_map;
for( DataMap::const_iterator it = data_map.begin(); it != data_map.end(); ++it)
{
Data*t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
other_map[it->first] = t;
std::cout << "INSERTED: " << std::hex << other_map[it->first] << std::endl;
}
std::cin.ignore();
return 0;
}
On VS2010SP1, this outputs :
CLONE: 00034DD0
INSERTED: 00034DD0
CLONE: 00035098
INSERTED: 00035098
So it should be the problem, or maybe you're doing something wrong before.
Try this out, to help debug the issue. I'd recommend double-checking that the order function is correct. You can remove it to use std::less<T>, which is known to work.
// ...
typedef std::map<std::string, data_base*, order> string_db_map;
for(string_db_map::const_iterator it = other.elements.begin();
it != other.elements.end();
++it)
{
data_base *t = it->second->clone();
std::cout << "CLONE: " << std::hex << t << std::endl;
std::pair<string_db_map::iterator, bool) result = elements.insert(
string_db_map::value_type( it->first, t));
if ( !result.second )
{
std::cout << "element['" << it->first << "'] was already present, and replaced." << std::endl;
}
std::coud << "INSERTED [iterator]: " << std::hex << (*result.first).second << std::endl;
std::cout << "INSERTED [indexed]: " << std::hex << elements[it->first] << std::endl;
}
// ...

TOUGH: Dealing with deeply nested pointers in C++

I define this structure:
struct s_molecule
{
std::string res_name;
std::vector<t_particle> my_particles;
std::vector<t_bond> my_bonds;
std::vector<t_angle> my_angles;
std::vector<t_dihedral> my_dihedrals;
s_molecule& operator=(const s_molecule &to_assign)
{
res_name = to_assign.res_name;
my_particles = to_assign.my_particles;
my_bonds = to_assign.my_bonds;
my_angles = to_assign.my_angles;
my_dihedrals = to_assign.my_dihedrals;
return *this;
}
};
and these structures:
typedef struct s_particle
{
t_coordinates position;
double charge;
double mass;
std::string name;
std::vector<t_lj_param>::iterator my_particle_kind_iter;
s_particle& operator=(const s_particle &to_assign)
{
position = to_assign.position;
charge = to_assign.charge;
mass = to_assign.mass;
name = to_assign.name;
my_particle_kind_iter = to_assign.my_particle_kind_iter;
return *this;
}
} t_particle;
struct s_bond
{
t_particle * particle_1;
t_particle * particle_2;
std::vector<t_bond_param>::iterator my_bond_kind_iter;
s_bond& operator=(const s_bond &to_assign)
{
particle_1 = to_assign.particle_1;
particle_2 = to_assign.particle_2;
my_bond_kind_iter = to_assign.my_bond_kind_iter;
return *this;
}
};
and then in my code I return a pointer to an s_molecule (typedef'd to t_molecule, but still).
Using this pointer I can get this code to work:
for (unsigned int i = 0;
i < current_molecule->my_particles.size();
i++)
{
std::cout << "Particle "
<< current_molecule->my_particles[i].name << std::endl
<< "Charge: "
<< current_molecule->my_particles[i].charge << std::endl
<< "Mass: "
<< current_molecule->my_particles[i].mass << std::endl
<< "Particle Kind Name: "
<< (*current_molecule->my_particles[i].my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << current_molecule->my_particles[i].position.x
<< " y: " << current_molecule->my_particles[i].position.y
#ifdef USE_3D_GEOM
<< "z: " << current_molecule->my_particles[i].position.z
#endif
<< std::endl;
}
If I replace it with:
for (std::vector<t_particle>::iterator it = current_molecule->my_particles.begin();
it !=current_molecule->my_particles.end();
it++)
{
std::cout << "Particle "
<< (*it).name << std::endl
<< "Charge: "
<< (*it).charge << std::endl
<< "Mass: "
<< (*it).mass << std::endl
<< "Particle Kind Name: "
<< (*(*it).my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << (*it).position.x
<< " y: " << (*it).position.y
#ifdef USE_3D_GEOM
<< "z: " << (*it).position.z
#endif
<< std::endl;
}
I now get nasty segfaults...
Not to put too much here, but I'm also getting segfaults when I tried to do this:
std::cout << "Bond ATOMS : "
<< (*current_molecule).my_bonds[0].particle_1->name
<< std::endl
Again, current_molecule is a pointer to a s_molecule structure, which contains arrays of structures, which in turn either directly have vars or are pointers. I can't get these multiple layers of indirection to work. Suggestions on fixing these segfaults.
FYI I'm compiling on Linux Centos 5.4 with g++ and using a custom makefile system.
#sbi Thanks for the good advice! I believe you are right -- the assignment overloaded operator is unnecessary and should be scrapped.
I've followed the approach of commenting out stuff and am very confused. Basically in the function that passes the pointer to my particular molecule to the main function to print, I can see all the data in that molecule (bonds, particles, name, etc) perfectly, printing with cout's.
Once I pass it to the main as a ptr, if I use that ptr with an iterator I get a segfault. In other words. Also for some reason the bond data (which I can freely print in my funct that returns to the pointer) also segfaults if I try to print it, even if I use the [] to index the vector of bonds (which works for the particle vector).
That's the best info I can give for now.
A wild guess: Are you using shared libraries. I remember having difficulties passing STL-containers back and forth across shared library boundaries.
Jason (OP) was asked in a comment by David Rodríguez:
Are you returning a pointer to a local variable?
Jason answered:
No its a ptr to a class variable. The class is very much in existence (it contains the function that returns the molecule).
Unless you're talking of a true class variable (qualified as static), the fact that the class exists doesn't have much to do with it. Instances of a class exist, and they might have ceased to exist even if you just called a function on them.
As such, the question is:
Does the instance of the class that returned the pointer current_molecule still exist?
Or is current_molecule qualified as static, i.e. being a true class variable?
If the answer to both questions is "no", you're in Undefined County.
At this point, it becomes very important that you post source code that can be used by us here to actually reproduce the problem; it might well be located in source you aren't showing us.
Again, this issue was answered here:
Weird Pointer issue in C++
by DeadMG. Sorry for the double post.