Initialize references to matrix element in struct - c++11

I have a struct that represents a 3D position. Sometimes it's convenient to access the individual components and sometimes it's convenient to access all components as a vector (physics vector not std::vector) for which I'm using the Eigen linear algebra library. Since there are only three elements (x, y, z) and will only ever be three elements, is there anything wrong with the struct having three double& that refer to the elements of the Eigen Matrix? i.e.:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition
{
EnuPosition(): pos(ColumnVector3::Zero()), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(double east, double north, double up): pos((ColumnVector3() << east, north, up).finished()),
east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const ColumnVector3& position): pos(position), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition(const EnuPosition& enu):pos(enu.pos), east(pos[0]), north(pos[1]), up(pos[2]) {}
EnuPosition& operator=(const EnuPosition& enu)
{
this->pos = enu.pos;
return *this;
}
ColumnVector3 pos;
double& east;
double& north;
double& up;
};
It compiles fine with no warnings on g++ 5.5 with -Wall -Wextra -pedantic in the use cases I can think of:
int main ()
{
EnuPosition enu{12.5, 34.2, 99.2};
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
ColumnVector3 x;
x << 2.0,3.0,4.0;
enu.pos = x;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::MatrixXd y;
y.resize(3,1);
y << 7.6,8.7,9.8;
enu.pos = y;
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
Eigen::Matrix<double,3,3> R;
enu.east = 1;
enu.north = 1;
enu.up = 1;
R << 1,2,3,4,5,6,7,8,9;
enu.pos = (R * enu.pos).eval();
std::cout << "east: " << enu.east
<< " north: " << enu.north
<< " up: " << enu.up
<< std::endl;
EnuPosition enu2 = enu;
std::cout << "east: " << enu2.east
<< " north: " << enu2.north
<< " up: " << enu2.up
<< std::endl;
}
Like I said, it works, I'm just curious if it's legal and not relying on undefined behavior, etc. Or are there other issues to be cognizant of?

After you added the copy-assignment your code should be safe.
However, if you are ok with writing east() instead of east in your code, then a slightly more elegant solution might be this:
using ColumnVector3 = Eigen::Matrix<double, 3, 1>;
struct EnuPosition : public ColumnVector3
{
EnuPosition(): ColumnVector3(ColumnVector3::Zero()) {}
EnuPosition(double east, double north, double up): ColumnVector3(east, north, up) {}
template<class X>
EnuPosition(const X& other): ColumnVector3(other) {}
double& east() {return this->x();}
double const& east() const {return this->x();}
double& north() {return this->y();}
double const& north() const {return this->y();}
double& up() {return this->z();}
double const& up() const {return this->z();}
};
If you intentionally don't want to inherit, you can of course still store the ColumnVector3 as a member.

Related

How to mix auto with brace-initialization to return a std::pair properly?

I have this example which is a function that returns a std::pair which holds a string value and its size.
std::pair<std::string, int> getLastPair(const vector<string>& vec) {
return{ vec.back(), vec.back().size() };
}
int main(){
vector<string> names{ "An", "Apple", "A", "Day", "Keeps", "The",
"Doctor", "Away"};
auto p{getLastPair(names)}; // ok p is a pair<string, int>
std::cout << p.first << " " << p.second << std::endl;
std::cout << typeid(p).name() << std::endl;
auto p2 = { getLastPair(names) }; // why it is not a pair but an initializer list?
std::cout << typeid(p2).name() << std::endl; // initializer list
std::pair<std::string, int> p3 = { getLastPair(names) }; // ok a pair
std::cout << p3.first << " : " << p3.second << std::endl;
decltype (getLastPair(names)) p4 = { getLastPair(names) }; // ok
std::cout << p4.first << " : " << p4.second << std::endl; // ok
}
Why the first initialization returns a pair as expected but the second one p2 is not a pair but an initializer_list instead?
As you can see p3 works fine (returns a pair) aslong as I've provided the type explicitly!?
Is the problem in Type Specifier auto?
Also p4 works fine with decltype.

problem with polygon_90_data and vertices

I create a boost polygon with 5 vertices, but when I display the vertices or
#include <boost/polygon/polygon.hpp>
.
.
.
void displayPolygon(boost::polygon::polygon_90_data<int> const& polygon, std::string name)
{
std::cout << std::endl << "polygon " << name << std::endl;
for (boost::polygon::polygon_90_data<int>::iterator_type it = polygon.begin(); it != polygon.end(); it++)
{
std::cout << (*it).x() << "/" << (*it).y() << "->";
}
std::cout << std::endl;
}
.
.
.
void testPolygon2()
{
//typedef
typedef boost::polygon::polygon_90_data<int> Polygon90Type;
typedef std::vector<Polygon90Type> Polygon90Set;
typedef boost::polygon::polygon_data<int> PolygonType;
typedef std::vector<PolygonType> PolygonSet;
typedef boost::polygon::point_data<int> PointType;
typedef std::vector<PointType> PointSet;
typedef boost::polygon::polygon_traits<Polygon90Type>::point_type Point;
Polygon90Type polygon_1;
Point pts_1[6] = { Point(0,0), Point(0,10), Point(5,12), Point(10,10), Point(10,0), Point(0,0)};
polygon_1.set(pts_1, pts_1 + 6);
std::cout << "polygon_1 area is " << boost::polygon::area(polygon_1) << std::endl;
std::cout << std::endl << __LINE__ << " :
Polygon90Set polygonSet;
polygonSet.push_back(polygon_1);
//an attempt to see result of bloating with 0
boost::polygon::bloat(polygonSet, 0, 0, 0, 0);
std::cout << "nb polygon bloated " << polygonSet.size() << std::endl;
for (auto polygon : polygonSet)
{
std::cout << std::endl << __LINE__ << "####################################" << std::endl;
displayPolygon(polygon, "2 - after being bloated");
std::cout << "area is " << boost::polygon::area(polygon) << std::endl;
}
}
the area it does not correspond to the polygon created.
the area should be 110 but is displayed as 100?
the vertices should be (0,0), (0,10), (5,12), (10,10), (10,0) but are (0/10), (5/10) ,(5/10), (10/10), (10/0), (0/0). It looks like the point (/5/12) is dismissed and replaced with point (5/10).
What am I doing wrong?
thanks.

POD-types and inheritance in c++11: Why is it not possible to inherit and extend, and still be a POD-type

I think this is best explained with an example:
#include <iostream>
struct A
{
int a;
};
struct B
{
A a;
int b;
};
struct C: A
{
int c;
};
static inline std::ostream& operator<< (std::ostream& os, const A& a)
{ return os << a.a; }
static inline std::ostream& operator<< (std::ostream& os, const B& b)
{ return os << b.a << " " << b.b; }
static inline std::ostream& operator<< (std::ostream& os, const C& c)
{ return os << c.a << " " << c.c; }
static_assert(std::is_pod<B>::value, "B");
static_assert(std::is_pod<A>::value, "A");
static_assert(std::is_trivial<C>::value, "C");
//static_assert(std::is_pod<C>::value, "C");
int main()
{
std::cout << "sizeof(A) " << sizeof(A) << std::endl;
std::cout << "sizeof(B) " << sizeof(B) << std::endl;
std::cout << "sizeof(C) " << sizeof(C) << std::endl;
B b = B{14,42};
std::cout << "b " << b << std::endl;
C c; c.a=15; c.c=43;
std::cout << "c " << c << std::endl;
B* bp = &b;
std::cout << "(C)b " << *(C*)(bp) << std::endl;
C* cp = &c;
std::cout << "(B)c " << *(B*)(cp) << std::endl;
return 0;
}
Output:
sizeof(A) 4
sizeof(B) 8
sizeof(C) 8
b 14 42
c 15 43
(C)b 14 42
(B)c 15 43
Why does C not qualify as standard_layout. As I would expect it has the same memory layout as B. What could potentially differ?

How to compose and form the binary literals, for example through the conversion from decimal in C++11 / C++14?

int main() {
int x = 3613;
std::cout << "x= " << x << std::endl;
std::string xBin = std::bitset<16>(x).to_string();
std::cout << xBin << std::endl;
unsigned long xDecimal = std::bitset<16>(xBin).to_ulong();
std::cout << xDecimal << std::endl;
std::cout << std::endl << std::endl;
int b01 = 0b11001;
std::cout << "b01= " << b01 << std::endl;
int b02 = 0b1010;
std::cout << "b02= " << b02 << std::endl;
int b03 = b01 + b02;
std::cout << "int b03 = b01 + b02 = " << b03 << std::endl;
return 0;
}
Output:
x= 3613
0000111000011101
3613
b01= 25
b02= 10
int b03 = b01 + b02 = 35
With binary literals we can do normal arithmetic operations, while with the strings obtained with std::bitset<> this is not possible.
So...the question is: how to "compose" the binary literals, for example through the conversion from decimal to binary as obtained using std::bitset<> ?
Looking forward to your kind help. Marco
You shouldn't operate on bitsets by converting them to string and back - that's missing the point of bitsets... Instead you operate on them by using binary operators: &, |, ^, ... (just like you would on usual integers).
std::cout << std::bitset<3>(4) << " or "
<< std::bitset<3>(2) << " = "
<< (std::bitset<3>(4) | std::bitset<3>(2)) << std::endl;
Prints: 100 or 010 = 110
You can find all operators on wiki: http://en.cppreference.com/w/cpp/utility/bitset

C++ 11- scopes & global variables

How can I reach global variables from inner scopes, given the following code sample, how can I reach the global string X from the main function and from the most inner scope as well, also is the most inner scope is accessible once we quit it to the main scope or other scope?
#include <iostream>
#include <string>
std::string x = "global";
int counter = 1;
int main()
{
std::cout <<counter ++ << " " << x << std::endl;
std::string x = "main scope";
std::cout <<counter ++ << " " << x << std::endl;
{
std::cout <<counter ++ << " " << x << std::endl;
std::string x = "inner scope";
std::cout <<counter ++ << " " << x << std::endl;
}
std::cout <<counter++ << " " << x << std::endl;
}
the cout currently is:
1 global
2 main scope
3 main scope
4 inner scope
5 main scope
Global scope can be reached by using ::x, as per:
#include <iostream>
#include <string>
std::string x = "global";
int counter = 1;
int main()
{
std::cout << counter++ << " " << x << std::endl;
std::string x = "main scope";
std::cout << " " << ::x << std::endl;
std::cout << counter++ << " " << x << std::endl;
{
std::cout << " " << ::x << std::endl;
std::cout << counter++ << " " << x << std::endl;
std::string x = "inner scope";
std::cout << " " << ::x << std::endl;
std::cout << counter++ << " " << x << std::endl;
}
std::cout << " " << ::x << std::endl;
std::cout << counter++ << " " << x << std::endl;
}
which gives you:
1 global
global
2 main scope
global
3 main scope
global
4 inner scope
global
5 main scope
The hard bit is actually getting to the intermediate scopes, such as main scope when you're withing the inner scope.
One way to do that is with references:
#include <iostream>
#include <string>
std::string x = "outer";
int main()
{
std::cout << "1a " << x << "\n\n";
std::string x = "middle";
std::cout << "2a " << ::x << '\n';
std::cout << "2b " << x << "\n\n";
{
std::string &midx = x; // make ref to middle x.
std::string x = "inner"; // hides middle x.
std::cout << "3a " << ::x << '\n';
std::cout << "3b " << midx << '\n'; // get middle x via ref.
std::cout << "3c " << x << "\n\n";
}
}
which gives:
1a outer
2a outer
2b middle
3a outer
3b middle
3c inner
But, as good advice, you'll find you won't have anywhere near as many problems if you:
name your variables a little more intelligently so as to avoid clashes; and
avoid global variables like the plague :-)
And, as for the variables in inner scopes, they cease to be available once you leave that scope, even with a reference (you can copy them to a variable with an larger scope but that's not the same as accessing the inner-scoped variable).

Resources