I am experimenting with polymorphism and boost::variant in c++11
Here is the code
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{
width=a;
height=b;
}
};
class Rectangle: public Polygon {
public:
Rectangle() {
std::cout << "ctor rectangle" << std::endl;
}
int area()
{
return width*height;
}
};
class Triangle: public Polygon {
public:
Triangle() {
std::cout << "ctor triangle" << std::endl;
}
int area()
{
return width*height/2;
}
};
int main () {
Triangle r;
boost::variant<Rectangle, Triangle> container = r;
int x = 4;
int y = 5;
if (container.type() == typeid(Rectangle)) {
r.set_values(x,y);
std::cout << r.area() << std::endl;
} else if ( container.type() == typeid(Triangle)){
r.set_values(x,y);
std::cout << r.area() << std::endl;
}
return 0;
}
I am wondering if this is the best way to proceed. There is a repetition in the code (in main() function) where for every type (we get the type at runtime) we execute the same thing, ie set value and print the area.
Is there any better way to do this?
This is a helper class for when you want value-type variant based polymorphism.
template<class Base>
struct poly_ptr_t : boost::static_visitor<Base*> {
template<class T>
Base* operator()(T& t)const { return std::addressof(t); }
template<class...Ts>
Base* operator[](boost::variant<Ts...>& v) const {
return boost::apply_visitor( *this, v );
}
template<class...Ts>
Base const* operator[](boost::variant<Ts...> const& v) const {
return boost::apply_visitor( *this, v );
}
};
Use:
poly_ptr_t<Polygon> as_polygon;
int main() {
boost::variant<Triangle, Rectangle> u(Triangle{});
as_polygon[u]->set_values(x,y);
}
Now, area is a bit of a pain. Getting the parent Polygon won't help, because it doesn't have an area.
If we added
virtual int area() = 0;
to Polygon then
std::cout << as_polygon[v]->area();
suddenly works.
The alternative is a bit of a mess in C++11. In C++14 with appropriate boost support, we get:
std::cout << boost::apply_visitor( [](auto& e){return e.area();}, v );
or
boost::apply_visitor( [](auto& e){std::cout << e.area();}, v );
where we use a generic lambda to call area.
Or we can write an area visitor:
struct get_area : boost::static_visitor<int> {
template<class T>
int operator()(T& t)const{ return t.area(); }
};
now we can do this:
std::cout << boost::apply_visitor( get_area, v );
In none of these cases do we have the code repetition within main.
Don't use if-else constructs.
Take a look at boost. I typed a small and untested example below.
#include "boost/variant.hpp"
#include <iostream>
class my_visitor : public boost::static_visitor<void>
{
public:
void operator()(Rectangle const & i) const
{
// do something here
}
void operator()(Triangle const & i) const
{
// do something here
}
};
int main()
{
boost::variant< Triangle, Rectangle > u(Triangle());
boost::apply_visitor( my_visitor(), u );
}
Related
Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.
So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?
I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.
What is the general pattern to solve such kind of problems?
#include <iostream>
template<typename T>
class AbstractClass {
virtual T getValue()=0;
};
class StringClass : public AbstractClass<std::string> {
std::string getValue() override {
return "A";
}
};
class FloatClass : public AbstractClass<float> {
float getValue() override {
return 1;
}
};
class Processor {
public:
AbstractClass<T>* ptr;
void doIt() {
ptr=new StringClass();
print(ptr->getValue());
delete ptr;
ptr=new FloatClass();
print(ptr->getValue());
delete ptr;
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:
#include <iostream>
#include <variant>
class StringClass {
std::string getValue() override {
return "A";
}
};
class FloatClass {
float getValue() override {
return 1;
}
};
using ClassWithGetValue = std::variant<StringClass, FloatClass>;
class Processor {
public:
ClassWithGetValue v;
void doIt() {
v = StringClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
v = FloatClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
Having a closer look at __do_visit in std::variant I grew curious about the performances of the std::variant polymorphic approach
I wrote a small test program to compare old school inheritance to the std::variant one
#include <variant>
#include <vector>
#include <iostream>
#include <string>
#include <chrono>
int i = 0;
// Polymorphism using variants
class circle
{
public:
void draw() const { i++; }
};
class line
{
public:
void draw() const { i++; }
};
using v_t = std::variant<circle, line>;
void variant_way(const std::vector<v_t>& v)
{
for (const auto &var : v)
std::visit([](const auto& o) {
o.draw();
}, var);
}
// old school
class shape
{
public:
virtual void draw() const = 0;
virtual ~shape() { }
};
class circle_in : public shape
{
public:
virtual void draw() const { i++; }
};
class line_in : public shape
{
public:
virtual void draw() const { i++; }
};
void inherit_way(const std::vector<shape*>& v)
{
for (const auto var : v)
var->draw();
}
// call and measure
template <typename F, typename D>
void run(F f, const D& data, std::string name)
{
auto start = std::chrono::high_resolution_clock::now();
f(data);
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << name << ": "<< elapsed.count() << std::endl;
}
int main()
{
constexpr int howmany = 100000;
{
std::vector<v_t> v {howmany};
run(variant_way, v, "variant");
}
{
std::vector<shape*> v;
for (int i = 0; i < howmany; i++)
v.push_back(new circle_in());
run(inherit_way, v, "inherit_way");
// deallocate
}
return 0;
}
On my machine (i7, 16GB RAM), I get these results:
variant: 7487
inherit_way: 1302
I suspect that this result reflects the fact that the std::variant approach creates the vtable at each iteration while the inheriting approach does it once for all.
Is this explanation correct?
Is there a way to reduce the overhead?
Background
I am creating a Cpp parser using Bison and Flex and I stumbled upon a problem: In my parser, I require a vector of base class objects, let's say shapes. Depending on which derived class an object has, I need to access different members. Thus, my intend was to store unique_ptr in the vector. Then upon access, I could dynamically cast them to their derived type.
The Problem
However, I can't get Bison to handle the unique_ptrs correctly. No matter how I specify the parser.yy file, upon compilation I run into errors like
usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
According to this post Bison does not handle unique_ptrs well (as far as I understand Bison does not use std::move() internally) and I assume that this is still the case.
My Question
As I would like to keep the class hierarchy as it is and don't want to fix bugs within Bison itself: Is there an alternative to using unique_ptrs when casting from Base class to Derived class?
Code Example
In particular, I want something like the following to work without using unique_ptrs.
enum Shape_type{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_TRIANGLE,
};
class Shape{
public:
enum Shape_type type;
Shape(enum Shape_type type){ this->type=type; }
virtual ~Shape(){}
};
class Circle: public Shape{
int r;
public:
int get_r(){ return this->r; }
Circle(int r):Shape(SHAPE_TYPE_CIRCLE){ this->r=r; }
};
int main(void){
std::vector<std::unique_ptr<Shape>> shapes;
std::unique_ptr<Shape> circle_ptr = std::make_unique<Circle>(42);
shapes.push_back(std::move(circle_ptr));
for(auto& s_ptr: shapes){
switch(s_ptr->type){
case SHAPE_TYPE_CIRCLE:
{
auto c = dynamic_cast<Circle&>(*s_ptr);
std::cout << "circle with r=" << c.get_r() << std::endl;
break;
}
default: {
std::cout << "other shape" << std::endl;
break;
}
}
}
return 0;
}
Any help is greately appreciated. Thanks in advance.
The polymorphic way would be (replacing non-copiable std::unique_ptr by std::shared_ptr):
class Shape{
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle: public Shape
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const override { std::cout << "circle with r=" << r << std::endl; }
};
class Square: public Shape
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const override { std::cout << "square with side=" << side << std::endl; }
};
int main()
{
std::vector<std::shared_ptr<Shape>> shapes { std::make_shared<Circle>(42) };
for (const auto& shape_ptr: shapes)
{
shape_ptr->draw();
}
return 0;
}
With std::variant, you might do
class Circle
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const { std::cout << "circle with r=" << r << std::endl; }
};
class Square
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const { std::cout << "square with side=" << side << std::endl; }
};
using Shape = std::variant<Circle, Square>;
int main()
{
std::vector<Shape> shapes { Circle(42) };
for (const auto& shape: shapes)
{
std::visit([](const auto& shape){ shape.draw(); }, shape);
}
return 0;
}
I've got this Map in my Entity-Component-System:
std::map<u_int32_t, std::vector<std::shared_ptr<Component>>> _componentMap;
The u_int32_t is the key to a vector of components. There can be multiple instances of the same component. (That's why there's a vector).
Now I would like to have a templated getter-function that returns a Vector of an inherited type:
template<class T> inline const std::vector<std::shared_ptr<T>> & getVector() const
{
u_int32_t key = getKey<T>();
return static_cast<std::vector<std::shared_ptr<T>>>(_componentMap.count(key) ? _componentMap.at(key) : _emptyComponentVec);
}
I know that this doesn't work, since std::vectors of different types are completely unrelated and I cannot cast between them. I would also like to avoid allocating a new vector every time this function is called.
But how I can I get the desired behaviour? When the the components are added I can create an std::vector of the desired derived type.
The question could also be: How can I have an std::map containing different types of std::vector?
For any solutions I can not link against boost, though if absolutely needed, I could integrate single headers of boost.
template<class It>
struct range_view {
It b, e;
It begin() const { return b; }
It end() const { return e; }
using reference = decltype(*std::declval<It const&>());
reference operator[](std::size_t n) const
{
return b[n];
}
bool empty() const { return begin()==end(); }
std::size_t size() const { return end()-begin(); }
reference front() const {
return *begin();
}
reference back() const {
return *std::prev(end());
}
template<class O>
range_view( O&& o ):
b(std::begin(o)), e(std::end(o))
{}
};
this is a quick range view. It can be improved.
Now all you need to do is write a pseudo-random-access iterator that converts its arguments. So it takes a random access iterator over a type T, then does some operation F to return a type U. It forwards all other operations.
The map then stores std::vector<std::shared_ptr<Base>>. The gettor returns a range_view< converting_iterator<spBase2spDerived> >.
Here is a crude implementation of a solution I have in mind for this problem. Of course, there are many rooms to refine the code, but hopefully it conveys my idea.
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
class Base {
public:
virtual void f() const = 0;
};
class A : public Base {
public:
static const int type = 0;
explicit A(int a) : a_(a) {}
void f() const { cout << "calling A::f" << endl;}
int a_;
};
class B : public Base {
public:
static const int type = 1;
explicit B(int a) : a_(a) {}
void f() const { cout << "calling B::f" << endl;}
int a_;
};
class MapWrapper {
public:
template<class T>
void append(int a, vector<T> const& vec) {
types_[a] = T::type;
my_map_[a] = make_shared<vector<T>>(vec);
}
template<class T>
vector<T> const& get(int a) const {
return *static_pointer_cast<vector<T>>( my_map_.at(a) );
}
map<int, shared_ptr<void>> const& get_my_map() const {
return my_map_;
}
vector<shared_ptr<Base>> get_base(int a) const {
vector<shared_ptr<Base>> ret;
switch(types_.at(a)) {
case 0: {
auto const vec = get<A>(a);
for(auto v : vec)
ret.push_back(make_shared<A>(v));
break;
}
case 1: {
auto const vec = get<B>(a);
for(auto v : vec)
ret.push_back(make_shared<B>(v));
break;
}
}
return ret;
}
map<int, shared_ptr<void>> my_map_;
map<int, int> types_;
};
int main() {
MapWrapper map_wrapper;
map_wrapper.append(10, vector<A>{A(2), A(4)});
map_wrapper.append(20, vector<B>{B(5), B(7), B(9)});
for(auto const& w : map_wrapper.get_my_map())
for(auto v : map_wrapper.get_base(w.first))
v->f();
for(auto const& x: map_wrapper.get<A>(10))
cout << x.a_ << " ";
cout << endl;
for(auto const& x: map_wrapper.get<B>(20))
cout << x.a_ << " ";
return 0;
}
The solution was to use reinterpret_cast:
template<class T> inline std::vector<std::shared_ptr<T>> * getVector() const
{
auto key = getKey<T>();
return reinterpret_cast<std::vector<std::shared_ptr<T>> *>( (_componentMap.count(key) ? _componentMap.at(key).get() : const_cast<std::vector<std::shared_ptr<Component>> *>(&_emptyComponentSharedPtrVec)) );
}
It's not very pretty but it does work fine and it fulfills all requirements.
I wonder how to hide a real property field (not make it private or public but force to use setters and getters) and provide him with simple setter and getter. So I wonder how to create api like:
private:
Property( int my_a);
public:
Property( int my_b);
...
{
set_my_a(1);
cout << get_my_a() << endl;
// my_a = 13; // will cause compiler error
...
How to create such thing via Boost preprocessor?
Do you really need to use boost preprocessor?
you have a solution without boost below:
// property.h
#include <stdio.h>
#define property(type) struct : public Property <type>
template <typename T>
class Property
{
protected:
T value;
public:
virtual T get() {
return value;
}
virtual void set(T new_value) {
value = new_value;
}
};
usage example:
// test.cpp
#include "property.h"
class Test {
public:
property(int) {} a;
property(int) {
int get() {
return value * 10;
}
} b;
property(int) {
void set(int x) {
value = x * 200;
}
} c;
property(int) {
int get() {
return value * 3000;
}
void set(int x) {
value = x * 443;
}
} d;
};
main()
{
Test t;
printf("i\ta\tb\tc\td\t\n");
for (int i=0; i<10; i++) {
t.a.set(i);
t.b.set(i);
t.c.set(i);
t.d.set(i);
printf("%i\t%i\t%i\t%i\t%i\n", i, t.a.get(), t.b.get(), t.c.get(), t.d.get());
}
}
The wikipedia solution in http://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B is good but needs a minimal modification to become useful, because without the protected statement you cant write your own getters and setters.
#include <iostream>
template <typename T>
class property {
protected:
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
operator T const & () const {
return value;
}
};
struct Bar {
property <bool> alpha;
struct :public property <int> {
int & operator = (const int &i) {
::std::cout << "new setter " << i << ::std::endl;
return value = i;
}
} bravo;
};
main()
{
Bar b;
b.alpha = false;
b.bravo = (unsigned int) 1;
}
You can change a little more if you want:
#include <iostream>
#define SETTER(type) public: type& operator=(const type new_value)
#define GETTER(type) public: operator type const & () const
template <typename T>
class Property {
protected:
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
template <typename T2> T2 & operator = (const T2 &i) {
::std::cout << "T2: " << i << ::std::endl;
T2 &guard = value;
throw guard; // Never reached.
}
operator T const & () const {
return value;
}
};
struct Bar {
Property <bool> alpha;
struct:Property <int> {
SETTER(int) {
value = new_value * 1000;
::std::cout << "new method " << new_value << ::std::endl;
return value;
}
GETTER(int) {
return value/1000;
}
} bravo;
};
main()
{
Bar b;
b.alpha = false;
b.bravo = (unsigned int) 1;
::std::cout << b.bravo << ::std::endl;
}
Rather than rewrite an example of the implementation, this is the link for one on Wikipedia: http://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
This basically forces the property to be accessed through getter/setter methods. The upgrade you would need to get your desired effect is the ability to pass functors to these properties. There are plenty of ideas on implementing these; the best approach I cannot advise and depends on your developmental needs. Personally, it feels like over engineering and prefer to just use Pimpl to hide my private details and just provide the getters/setters explicitly.