apply_visitor does not change object - c++

I have inherited from boost::static_visitor<> and defined a class as follows:
class move_visitor : public boost::static_visitor<> {
private:
double m_dx, m_dy;
public:
move_visitor() : m_dx(0.0), m_dy(0.0) {}
move_visitor(double dx, double dy) : m_dx(dx), m_dy(dy) {}
~move_visitor() {}
void operator () (Point &p) const {
p.X(p.X() + m_dx);
p.Y(p.Y() + m_dy);
}
void operator () (Circle &c) const {
Point center_point(c.CentrePoint().X() + m_dx, c.CentrePoint().Y() + m_dy);
c.CentrePoint(center_point);
}
void operator() (Line &l) const {
Point start(l.Start().X() + m_dx, l.Start().Y() + m_dy),
end(l.End().X() + m_dx, l.End().Y() + m_dy);
l.Start(start);
l.End(end);
}
};
This class is supposed to change the x and y position of some objects, Point, Line and Circle.
When I execute the following code:
int main()
{
typedef boost::variant<Point, Line, Circle> ShapeType;
Point p(1, 2);
Line l(p, p);
Circle c(p, 5);
ShapeType shape_variant;
std::cout << p << "\n\n"
<< l << "\n\n"
<< c << "\n\n";
shape_variant = p;
boost::apply_visitor(move_visitor(2, 2), shape_variant);
std::cout << p << std::endl;
shape_variant = l;
boost::apply_visitor(move_visitor(2, 2), shape_variant);
std::cout << std::endl << l << std::endl;
return 0;
}
p remains as 1, 2 and so does l. Why aren't my object changing after 'apply_visitor`?

You're modifying shape_variant, not p or l.
Try
std::cout << boost::get<Point>(shape_variant) << std::endl;
and
std::cout << boost::get<Line>(shape_variant) << std::endl;

Related

How do I switch this to unique_ptr?

How do I make it so I dont have to manually delete the pointer?
With unique_ptr in the vector<> ?
Here is my code:
class vec2 {
public:
double x;
double y;
vec2() {
x = 0.0;
y = 0.0;
}
vec2(double xx, double yy) {
x = xx;
y = yy;
cout << "constructor called" << endl;
}
~vec2() {
static int count = 0;
cout << "destructor " << count << endl;
count++;
}
virtual double Length() { return sqrt(x * x + y * y); }
bool operator==(vec2& v) { return x == v.x && y == v.y; }
virtual string toString() {
stringstream s("");
s << "[" << x << " " << y << "]";
return s.str();
}
};
int main() {
vector<vec2*> vecs;
vecs.push_back(new vec2(1.8, 1.7));
vecs.push_back(new vec2(1.99, 1.7));
for (vec2* v : vecs) {
cout << v->toString() << endl;
delete v;
}
}
http://www.xgdev.com/notepad/textfiles/37631a.txt
Simple:
std::vector<std::unique_ptr<vec2>> vecs;
vecs.reserve(2); // Optional
vecs.push_back(std::make_unique<vec2>(1.8 ,1.7));
vecs.push_back(std::make_unique<vec2>(1.99, 1.7));
for (auto& v : vecs) {
cout << v->toString() << endl;
}
If you have virtual member function(s), most probably, destructor should also be virtual.

Automatically convert one c++ type to another

I am trying to make converting between a custom class and OpenCV easier.
Converting constructors allow us to declare a class without the explicit keyword and construct from an alternate data type.
For example, we could declare two classes:
class Foo
{
public:
std::vector<int32_t> data;
Foo(int k) : data(k) {}
};
class FooProxy : public cv::Mat
{
public:
FooProxy(const Foo & foo) : cv::Mat(foo.data.size(), 1, CV_32SC1, (void*)foo.data.data()) {}
};
And then we can create a FooProxy by setting it equal and then then using any OpenCV function we want:
Foo myFoo(3);
myFoo.data = { 1,2,3 };
FooProxy fp = myFoo;
fp.setTo(1);
float myNorm = cv::norm(fp);
std::cout << "myFoo: " << myFoo.data.at(0) << ", " << myFoo.data.at(1) << ", " << myFoo.data.at(2) << "\n";
std::cout << "fp: " << fp.at<int32_t>(0) << ", " << fp.at<int32_t>(1) << ", " << fp.at<int32_t>(2) << "\n";
std::cout << "The Norm is: " << myNorm << "\n";
with output:
myFoo: 1, 1, 1
fp: 1, 1, 1
The Norm is: 1.73205
However, I would much rather write:
float myNorm = cv::norm(myFoo);
and have c++ automatically convert myFoo. Is this possible?
This works:
float myNorm2 = cv::norm(FooProxy(myFoo));
but not the simpler version.
You could create a conversion operator
class Foo
{
...
operator cv::Mat()
{
return cv::Mat(data.size(), 1, CV_32SC1, (void*)data.data());
}
};
Edit cv::norm has the following overloads (notice no cv::Mat):
cv::norm(const Matx< _Tp, m, n > &M)
cv::norm(const Matx< _Tp, m, n > &M, int normType)
cv::norm(InputArray src1, int normType=NORM_L2, InputArray mask=noArray()) // this is the one we want
cv::norm(InputArray src1, InputArray src2, int normType=NORM_L2, InputArray mask=noArray())
cv::norm(const SparseMat &src, int normType)
A cv::InputArray can be constructed from a cv::Mat, however you're only allowed 1 user-defined conversion implicitly. So you'll actually need a conversion operator for cv::InputArray if you want Foo to work with cv::norm.
Then you should define a function in namespace cv like this:
namespace cv{
float norm(const Foo& foo){
return cv::norm(FooProxy(foo));
}
}
Now you can call:
float res = cv::norm(myFoo);
The code:
//! 2018.01.17 09:42:16 CST
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
class Foo
{
public:
std::vector<int32_t> data;
Foo(int k) : data(k) {}
};
class FooProxy : public cv::Mat
{
public:
FooProxy(const Foo & foo) : cv::Mat(foo.data.size(), 1, CV_32SC1, (void*)foo.data.data()) {}
};
namespace cv {
float norm(const Foo& foo) {
return cv::norm(FooProxy(foo));
}
}
int main() {
Foo myFoo(3);
myFoo.data = { 1,2,3 };
FooProxy fp = myFoo;
fp.setTo(1);
float myNorm = cv::norm(fp);
std::cout << "myFoo: " << myFoo.data.at(0) << ", " << myFoo.data.at(1) << ", " << myFoo.data.at(2) << "\n";
std::cout << "fp: " << fp.at<int32_t>(0) << ", " << fp.at<int32_t>(1) << ", " << fp.at<int32_t>(2) << "\n";
std::cout << "The Norm is: " << myNorm << "\n";
float myNorm2 = cv::norm(FooProxy(myFoo));
std::cout << "The Norm2 is:"<<myNorm2<<endl;
float myNorm3 = cv::norm(myFoo);
std::cout << "The Norm3 is:"<<myNorm2<<endl;
}
The result:
myFoo: 1, 1, 1
fp: 1, 1, 1
The Norm is: 1.73205
The Norm2 is:1.73205
The Norm3 is:1.73205

Params passed to variadic function via function pointer change their value

I have a class with some static functions and a map that contains pointers to these functions:
class Conditions
{
using cbType = bool(*)();
static std::unordered_map<std::string, cbType> const m_FunctionMap;
static bool Equal_int(const int A, const int B) { return A == B; }
static bool Equal_float(const float A, const float B) { return A == B; }
static bool Greater_int(const int A, const int B) { return A > B; }
static bool Greater_float(const float A, const float B) { return A > B; }
static bool Between_int(const int A, const int B, const int C) { return A > B && A < C; }
static bool Between_float(const float A, const float B, const float C) { return A > B && A < C; }
};
Thus, the static functions can have different numbers of parameters with different types. In the .cpp file I am initializing that map:
std::unordered_map<std::string, Conditions::cbType> const Conditions::m_FunctionMap
{
{ "Equal_int", MakeMapVal(&Equal_int) },
{ "Equal_float", MakeMapVal(&Equal_float) },
{ "Greater_int", MakeMapVal(&Greater_int) },
{ "Greater_float", MakeMapVal(&Greater_int) },
{ "Between_int", MakeMapVal(&Between_int) },
{ "Between_float", MakeMapVal(&Between_float) },
};
Then I added a method to the class Conditions to call these static functions by their name:
template <typename ... argsType>
static bool Call(std::string const& Key, argsType&& ... Args)
{
using prototype = bool(*)(argsType ...);
return reinterpret_cast<prototype>(m_FunctionMap.at(Key))(Args ...);
//return reinterpret_cast<prototype>(m_FunctionMap.at(Key))(std::forward<argsType>(Args) ...); // this has the same issue
}
Now when I run this code, call the Call(std::string const& Key, argsType&& ... Args) method that correctly calls the respective static function. For example:
Call("Greater_int", 42, 40);
However, within the Greater_int() function those two parameters are not 42 and 40 any more, but some random values. But in the Call function those values are correctly 42 and 40. Thuse those values change when calling the function pointers via reinterpret_cast.
Any ideas what I am doing wrong here?
You are in the wilderness of undefined behavior. Your reinterpret_cast is casting from unrelated types, and this is just bad. Remove the cast and make compiler happy some other way.
Unless I'm misundersdtanding, you want to create a DSL that allows parsing and comparison of dissimilar types.
This can be done very easily with boost::variant. It's just some boilerplate and a matter of defining the comparison operations of the dissimilar types.
Small but complete example:
#include <boost/variant.hpp>
#include <boost/operators.hpp>
#include <string>
#include <iostream>
#include <iomanip>
// define the concept of equality in my scripting language
struct is_equal : boost::static_visitor<bool>
{
// x == x is easy
template<class T>
bool operator()(const T& l, const T& r) const {
return l == r;
}
// define the concept of comparing strings to integers
bool operator()(const std::string& l, const int& r) const {
return l == std::to_string(r);
}
// and integers to strings
bool operator()(const int& l, const std::string& r) const {
return (*this)(r, l);
}
};
struct is_less : boost::static_visitor<bool>
{
// x == x is easy
template<class T>
bool operator()(const T& l, const T& r) const {
return l < r;
}
// define the concept of comparing strings to integers
bool operator()(const std::string& l, const int& r) const {
return l < std::to_string(r);
}
// and integers to strings
bool operator()(const int& l, const std::string& r) const {
return (*this)(r, l);
}
};
struct emit : boost::static_visitor<std::ostream&>
{
emit(std::ostream& os) : os_(os) {}
// x == x is easy
template<class T>
std::ostream& operator()(const T& l) const {
return os_ << l;
}
std::ostream& operator()(const std::string& s) const {
return os_ << std::quoted(s);
}
std::ostream& os_;
};
struct scriptable_value
: boost::less_than_comparable<scriptable_value>
, boost::equality_comparable<scriptable_value>
{
using variant_type = boost::variant<std::string, int>;
scriptable_value(std::string v) : variant_(std::move(v)) {}
scriptable_value(int v) : variant_(v) {}
variant_type const& as_variant() const {
return variant_;
}
private:
variant_type variant_;
};
bool operator==(scriptable_value const& l, scriptable_value const& r)
{
return boost::apply_visitor(is_equal(), l.as_variant(), r.as_variant());
}
bool operator<(scriptable_value const& l, scriptable_value const& r)
{
return boost::apply_visitor(is_less(), l.as_variant(), r.as_variant());
}
std::ostream& operator<<(std::ostream& os, scriptable_value const& r)
{
return boost::apply_visitor(emit(os), r.as_variant());
}
int main()
{
auto x = scriptable_value(10);
auto y = scriptable_value("10");
auto x2 = scriptable_value(9);
auto y2 = scriptable_value("9");
std::cout << x << " == " << y << " : " << std::boolalpha << (x == y) << std::endl;
std::cout << x << " != " << y << " : " << std::boolalpha << (x != y) << std::endl;
std::cout << x << " == " << y2 << " : " << std::boolalpha << (x == y2) << std::endl;
std::cout << x << " != " << y2 << " : " << std::boolalpha << (x != y2) << std::endl;
std::cout << x << " < " << y << " : " << std::boolalpha << (x < y) << std::endl;
std::cout << x << " >= " << y << " : " << std::boolalpha << (x >= y) << std::endl;
std::cout << x << " < " << y2 << " : " << std::boolalpha << (x < y2) << std::endl;
std::cout << x << " >= " << y2 << " : " << std::boolalpha << (x >= y2) << std::endl;
std::cout << x << " == " << x2 << " : " << std::boolalpha << (x == x2) << std::endl;
std::cout << x << " != " << x2 << " : " << std::boolalpha << (x != x2) << std::endl;
}
expected output:
10 == "10" : true
10 != "10" : false
10 == "9" : false
10 != "9" : true
10 < "10" : false
10 >= "10" : true
10 < "9" : false
10 >= "9" : true
10 == 9 : false
10 != 9 : true

Virtual function never gets called

I am trying to implement comparison between different subclasses of the same base class. The comparison should return false if the two instances are of different subclass or return the actual comparison result if they are of the same subclass.
Check the last line in function main: although I have declared equalTo as virtual, only the equalTo method of the base class is called. What is my mistake?
Thanks in advance.
#include <iostream>
#include <fstream>
#include <cmath>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <algorithm>
using namespace std;
bool fileInput = false, fileOutput = false;
class Point
{
public:
double x,y;
Point(){};
Point(double x1, double y1) {
x=x1;
y=y1;
}
bool operator==(Point other) const
{
return (abs(x - other.x) < numeric_limits<double>::epsilon()) and (abs(y - other.y) < numeric_limits<double>::epsilon());
}
};
class Shape
{
protected:
virtual double area() const
{
return 0;
}
virtual void print(std::ostream& os) const {}
virtual void read(std::istream& is) {}
public:
bool compare(Shape* other) {
return area() < other->area();
}
virtual bool equalTo(Shape other) const {
cout << "original";
return false;
}
friend std::ostream& operator<<(std::ostream &strm, const Shape &t)
{
t.print(strm);
return strm;
}
friend std::istream& operator>>(std::istream &strm, Shape &t)
{
t.read(strm);
return strm;
}
};
class Circle : public Shape
{
Point c;
double r;
double area() const
{
return M_PI * r * r;
}
void print(std::ostream &strm) const
{
strm << "Circle. Center coordinates: (" << c.x << "," << c.y << "). Radius: " << r << ". Area: " << area();
}
void read(std::istream &strm)
{
if (!fileInput) cout << "Enter Circle\nCenter: ";
strm >> c.x >> c.y;
if (!fileInput) cout << "Radius: ";
strm >> r;
if (r<0)
throw std::invalid_argument( "The radius cannot be negative." );
}
public:
Circle() {}
Circle(Point x, double y)
{
c = x;
r = y;
}
bool equalTo(Shape other1) const
{
Circle* other = dynamic_cast<Circle*>(&other1);
if (other == 0) return false;
return (c == other->c) and (abs(r - other->r)<numeric_limits<double>::epsilon());
}
};
class Hexagon : public Shape
{
Point c;
double r;
double area() const
{
return 1.5 * sqrt(3) * r * r;
}
void print(std::ostream &strm) const
{
strm << "Hexagon. Center coordinates: (" << c.x << "," << c.y << "). Circumcircle radius: " << r << ". Area: " << area();
}
void read(std::istream &strm)
{
if (!fileInput) cout << "Enter Hexagon\nCenter: ";
strm >> c.x >> c.y;
if (!fileInput) cout << "Circumcircle radius: ";
strm >> r;
if (r<0)
throw std::invalid_argument( "The circumcircle radius cannot be negative." );
}
public:
Hexagon() {}
Hexagon(Point x, double y)
{
c = x;
r = y;
}
bool equalTo(Shape other1) const
{
Hexagon* other = dynamic_cast<Hexagon*>(&other1);
if (other == 0) return false;
return (c == other->c) and (abs(r - other->r)<numeric_limits<double>::epsilon());
}
};
int main()
{
Shape c1 = Circle(Point(0,0), 3);
Shape c2 = Circle(Point(0,0), 3);
Shape c3 = Hexagon(Point(0,0), 3);
cout << "circles: " << c1.equalTo(c2) << endl << "diff: " << c1.equalTo(c3) << endl;
}
This is slicing, when you assign objects to object of type Shape - object was sliced to Shape. Use pointers, or may be references.
Circle p1(Point(0, 0), 3);
Circle p2(Point(0, 0), 3);
Hexagon h1(Point(0, 0), 3);
Shape& c1 = p1;
Shape& c2 = p2;
Shape& c3 = h1;
When you copy-construct a Shape out of a derived class, the object will be sliced so that only the Shape part of it is preserved. Then when you call equalTo, the function is statically bound.
In order to call the derived versions, make c1 and friends into Shape&.

dynamic_cast vs static_cast to void*

In the last two lines of below program, static_cast<void*> and dynamic_cast<void *> behave differently. From what I understand, The result of a dynamic_cast<void*> always resolves to the address of the complete object. So it uses RTTI in some way. Could anyone explain how compilers uses RTTI to differentiate between the two.
#include <iostream>
using namespace std;
class Top {
protected:
int x;
public:
Top(int n) { x = n; }
virtual ~Top() {}
friend ostream& operator<<(ostream& os, const Top& t) {
return os << t.x;
}
};
class Left : virtual public Top {
protected:
int y;
public:
Left(int m, int n) : Top(m) { y = n; }
};
class Right : virtual public Top {
protected:
int z;
public:
Right(int m, int n) : Top(m) { z = n; }
};
class Bottom : public Left, public Right {
int w;
public:
Bottom(int i, int j, int k, int m): Top(i), Left(0, j), Right(0, k) { w = m; }
friend ostream& operator<<(ostream& os, const Bottom& b) {
return os << b.x << ',' << b.y << ',' << b.z<< ',' << b.w;
}
};
int main() {
Bottom b(1, 2, 3, 4);
cout << sizeof b << endl;
cout << b << endl;
cout << static_cast<void*>(&b) << endl;
Top* p = static_cast<Top*>(&b);
cout << *p << endl;
cout << p << endl;
cout << static_cast<void*>(p) << endl;
cout << dynamic_cast<void*>(p) << endl;
return 0;
}
Possible output: https://ideone.com/WoX5DI
28
1,2,3,4
0xbfcce604
1
0xbfcce618
0xbfcce618
0xbfcce604
From 5.2.7 / 7:
If T is "pointer to cv void," then the result is a pointer to the most
derived object pointed to by v. Otherwise, a run-time check is applied
to see if the object pointed or referred to by v can be converted to
the type pointed or referred to by T.
So using dynamic_cast<void*>(o) you get a pointer to the first byte of the most "derived" object (if o is polymorphic).
The code the compiler generates for dynamic_cast<void *>(...) is something like:
static_cast<void*>(dynamic_cast<most_derived_type *>(...))
This property is often used for serialization.