I have a tree of polymorphic objects. I need to traverse the two trees and compare the nodes. If the nodes have different types, they are not equal. Consider this hierarchy:
struct Visitor;
struct Base {
virtual ~Base() = default;
virtual void accept(Visitor &) = 0;
};
using BasePtr = std::unique_ptr<Base>;
struct A final : Base {
void accept(Visitor &) override;
int data;
};
struct B final : Base {
void accept(Visitor &) override;
BasePtr child;
};
struct C final : Base {
void accept(Visitor &) override;
std::vector<BasePtr> children;
};
struct Visitor {
virtual void visit(const A &) = 0;
virtual void visit(const B &) = 0;
virtual void visit(const C &) = 0;
};
I know how to implement these functions:
bool equalNode(const A &, const A &);
bool equalNode(const B &, const B &);
bool equalNode(const C &, const C &);
I'm asking about how I should implement this function:
bool equalTree(const Base *, const Base *);
How do I elegantly go from equalTree to equalNode possibly using the visitor pattern?
Something like
struct RhsVisitor : public Visitor
{
bool result;
};
struct AEqualVisitor : public RhsVisitor
{
void visit(const A & rhs) override { result = equalNode(lhs, rhs); }
void visit(const B &) override { result = false; }
void visit(const C &) override { result = false; }
const A & lhs;
};
And similar for B and C
struct LhsVisitor : public Visitor
{
void visit(const A & a) override { rhsVisitor = std::make_unique<AEqualVisitor>(a); }
void visit(const B & b) override { rhsVisitor = std::make_unique<BEqualVisitor>(b); }
void visit(const C & c) override { rhsVisitor = std::make_unique<CEqualVisitor>(c); }
std::unique_ptr<RhsVisitor> rhsVisitor;
};
bool equalTree(const Base * lhs, const Base * rhs)
{
LhsVisitor vis;
lhs->accept(vis);
rhs->accept(*vis.rhsVisitor);
return vis.rhsVisitor->result;
};
There are three approaches here.
The first is - you need to do double dispatch. You have one visitor for one side and one visitor for the other side. Once you pick one side, you "save" that type as a template parameter, which you can use to visit the other side:
template <typename T>
struct Right : Visitor {
Right(T const* lhs) : lhs(lhs) { }
T const* lhs;
bool result;
void visit(A const& x) override { visit_impl(x); }
void visit(B const& x) override { visit_impl(x); }
void visit(C const& x) override { visit_impl(x); }
void visit_impl(T const& x) { result = equalNode(*lhs, x); }
template <typename U> void visit_impl(U const&) { result = false; }
};
struct Left : Visitor {
Left(Base const* lhs, Base const* rhs) : rhs(rhs) {
lhs->accept(*this);
}
Base const* rhs;
bool result;
void visit(A const& x) override { visit_impl(x); }
void visit(B const& x) override { visit_impl(x); }
void visit(C const& x) override { visit_impl(x); }
template <typename U>
void visit_impl(U const& lhs) {
Right<U> right(&lhs);
rhs->accept(right);
result = right.result;
}
};
bool equalTree(const Base *lhs, const Base *rhs) {
return Left(lhs, rhs).result;
}
The second is - you cheat. You only care about the cases where the two sides are the same type, so you only need single dispatch:
struct Eq : Vistor {
Eq(Base const* lhs, Base const* rhs) : rhs(rhs) {
lhs->accept(*this);
}
Base const* rhs;
bool result;
void visit(A const& x) override { visit_impl(x); }
void visit(B const& x) override { visit_impl(x); }
void visit(C const& x) override { visit_impl(x); }
template <typename U>
void visit_impl(U const& x) {
result = equalNode(x, *static_cast<U const*>(rhs));
}
};
bool equalTree(Base const* lhs, Base const* rhs) {
if (typeid(*lhs) == typeid(*rhs)) {
return Eq(lhs, rhs).result;
} else {
return false;
}
}
The third is - you don't do this through OO and instead use a variant:
using Element = std::variant<A, B, C>;
struct Eq {
template <typename T>
bool operator()(T const& lhs, T const& rhs) const {
return equalNode(lhs, rhs);
}
template <typename T, typename U>
bool operator()(T const&, U const&) const {
return false;
}
};
bool equalTree(Element const& lhs, Element const& rhs) {
return std::visit(Eq{}, lhs, rhs);
}
Related
I have to pass around the void * for supporting types that can't be known at compile time, but I also don't want to go totally insane and left everything on myself so I think to use type_info for type_Checking but since type_info doesn't support copy operation I am getting compiler errors when passing them around
#include <bits/stdc++.h>
struct PropertyClassInterface {
virtual const char * name() = 0;
virtual void set(const char * property_name,std::pair<const void *,std::type_info> new_val) = 0;
virtual std::pair<std::shared_ptr<void>,std::type_info> get(const char * property_name) = 0;
template< typename Type>
static std::pair<std::shared_ptr<void>,std::type_info> get_type_pair(const Type& Value) {
std::shared_ptr<void> t = std::make_shared<Type>();
*static_cast<Type *>(t.get()) = Value;
*return std::make_pair(t,typeid(Type));* // error
}
};
struct PropertyManager {
using base_pointer = std::shared_ptr<PropertyClassInterface>;
void add_object(base_pointer new_member) {
objects.push_back(new_member);
}
template<typename Type>
void set(const char * object_name,const char * property_name,const Type& new_val) {
find_object_orThrow(object_name)->set(property_name,std::make_pair(static_cast<const void *>(&new_val),typeid(new_val)));
}
template<typename Type>
Type get(const char * object_name, const char * property_name) {
auto a = find_object_orThrow(object_name)->get(property_name);
if (typeid(Type).hash_code() != a.second.hash_code())
throw std::runtime_error{"get(): mismatched type"};
return a.first;
}
public:
std::vector<base_pointer> objects;
base_pointer find_object_orThrow(const char * obj_name){
for(auto& o : objects) {
if (!strcmpi(o->name(),obj_name)) {
return o;
}
}
throw std::runtime_error{std::string("no object named \"") + obj_name + "\" found"};
}
};
struct testClass : PropertyClassInterface {
void set(const char * property_name,std::pair<const void *,std::type_info> new_val) {
auto checkTypeInfo = [&new_val](const std::type_info& expected) {
if (new_val.second.hash_code() != expected.hash_code())
throw std::runtime_error{"set(): wrong type"};
};
if (!strcmpi(property_name,"my_number")) {
checkTypeInfo(typeid(decltype(my_number)));
my_number = *static_cast<const decltype(my_number) *>(new_val.first);
}
};
std::pair<std::shared_ptr<void>,std::type_info> get(const char * property_name) {
if (!strcmpi(property_name,"my_number")) {
PropertyClassInterface::get_type_pair(my_number);
}
}
private:
int my_number;
};
int main() {
};
so do I have to use dynamic memory for storing type_info as well
I am limited to c++11 and I know about not using bits headers and am only using for testing
What you want to do is implement an any, or use boost any.
An any isn't hard to write.
namespace details {
struct any_concept;
using pimpl=std::unique_ptr<any_concept>;
struct any_concept {
virtual ~any_concept() {}
virtua pimpl clone() const = 0;
virtual std::type_info const& type() const = 0;
private:
virtual void* unsafe_get() = 0;
virtual void const* unsafe_get() const = 0;
public:
template<class T>
T* get() {
if (typeid(T) != type()) return nullptr;
return static_cast<T*>(unsafe_get());
}
template<class T>
T const* get() const {
if (typeid(T) != type()) return nullptr;
return static_cast<T const*>(unsafe_get());
}
};
template<class T>
struct any_model:any_concept {
T t;
virtual ~any_model() = default;
virtual pimpl clone() const final override {
return pimpl( new any_model(t) );
}
virtual std::type_info const& type() const final override {
return typeid(T);
}
template<class U>
any_model(U&& u):t(std::forward<U>(u)){}
private:
virtual void* unsafe_get() final override { return std::addressof(t); }
virtual void const* unsafe_get() const final override { return std::addressof(t); }
};
}
struct any {
template<class T, typename std::enable_if<!std::is_same<any, typename std::decay<T>::type>::value, bool> =true>
any( T&& t ):
pImpl( new details::any_model<typename std::decay<T>::type>( std::forward<T>(t) ) )
{}
template<class T>
T* get() {
if (!pImpl) return nullptr;
return pImpl->get<T>();
}
template<class T>
T const* get() const {
if (!pImpl) return nullptr;
return const_cast<details::any_concept const&>(*pImpl).get<T>();
}
template<class T>
bool contains()const { return get<T>(); }
explicit operator bool() const {
return (bool)pImpl;
}
any()=default;
any(any&&)=default;
any& operator=(any&&)=default;
~any()=default;
any(any const& o):
pImpl( o.pImpl?o.pImpl->clone():pimpl{} )
{}
any& operator=(any const& o) {
any tmp(o);
std::swap(*this, tmp);
return *this;
}
private:
details::pimpl pImpl;
};
there; a really simple any implementation. Written on a phone, so probably contains typos.
It supports value semantics, but store anything (that can be copied and destroyed). If you know what it stores, you can .get<T>() it. You can ask it if it contains<T>() as well.
This is known as a vocabulary type. It is basically your void* and type info bundled in a way that makes misuse more difficult.
How do I get an overloaded relational operator in a class to be called from a function in the parent class that is handed a const reference to a base class as a parameter? The following code demonstrates what I would like to do:
class Object
{
public:
virtual ~Object(void);
virtual int compare(Object const& obj) const;
};
int Object::compare(Object const & obj) const {
if(this == &obj)
{
return 0;
}
else if(this < &obj)
{
return -1;
} else{
return 1;
}
}
class Integer: public Object
{
private:
int myInt;
public:
Integer(int i);
bool operator==(const Integer& integer);
};
bool Integer::operator==(Integer const &integer) {
if(myInt == integer.myInt)
{
return true;
}
return false;
}
How do I get the compare function in the base class to call the == operator in the child class, keeping in mind I have other child classes as well?
I have tried dynamic_cast<> but for some reason it wont work.
You can add another virtual method isEqual to connect with the Integer::operator==.
The only requirement is to keep the Object::isEqual signature in the class Integer. You should also keep in mind that your Object::compare method can be (accidentally) called on objects of different types.
class Object
{
protected:
virtual bool isEqual(Object const& obj) const
{ return this == &obj; }
public:
virtual ~Object(void);
virtual int compare(Object const& obj) const;
};
int Object::compare(Object const & obj) const {
if(isEqual(obj))
{
return 0;
}
else if(this < &obj)
{
return -1;
} else{
return 1;
}
}
class Integer: public Object
{
private:
int myInt;
protected:
virtual bool isEqual(Object const& obj) const
{ if (!dynamic_cast<const Integer*>(&obj))
return false;
return *this == (const Integer&) obj;
}
public:
Integer(int i);
bool operator==(const Integer& integer);
};
I would do:
#include <iostream>
class Object
{
public:
virtual ~Object(void) {};
int compare(Object const& obj) const;
virtual bool operator==(Object const& integer) const = 0;
virtual bool operator<(Object const& integer) const = 0;
virtual bool operator>(Object const& integer) const = 0;
};
int Object::compare(Object const& obj) const
{
if(*this == obj)
return 0;
else if(*this < obj)
return -1;
else return 1;
}
class Integer: public Object
{
private:
int myInt;
public:
Integer(int i) : myInt(i) { };
virtual bool operator==(Object const& integer) const override;
virtual bool operator<(Object const& integer) const override;
virtual bool operator>(Object const& integer) const override;
};
bool Integer::operator==(Object const& integer) const
{
return myInt == dynamic_cast<Integer const&>(integer).myInt;
}
bool Integer::operator<(Object const& integer) const
{
return myInt < dynamic_cast<Integer const&>(integer).myInt;
}
bool Integer::operator>(Object const& integer) const
{
return myInt > dynamic_cast<Integer const&>(integer).myInt;
}
int main()
{
Integer a(2), b(2), c(3);
std::cout << a.compare(b) << std::endl;
std::cout << b.compare(c) << std::endl;
std::cout << c.compare(a) << std::endl;
}
But in reality you should just provide virtual compare function in inherited class like so:
class Object
{
public:
virtual ~Object(void) {};
virtual int compare(Object const& obj) const = 0;
};
class Integer: public Object
{
private:
int myInt;
public:
Integer(int i) : myInt(i) { };
virtual int compare(Object const& object) const override;
bool operator==(Integer const& integer) const;
bool operator<(Integer const& integer) const;
bool operator>(Integer const& integer) const;
};
int Integer::compare(Object const& object) const
{
Integer const& ref = dynamic_cast<Integer const&>(object);
if(ref == *this)
return 0;
else if(ref > *this)
return 1;
else return -1;
}
bool Integer::operator==(Integer const& integer) const
{
return myInt == integer.myInt;
}
bool Integer::operator<(Integer const& integer) const
{
return myInt > integer.myInt;
}
bool Integer::operator>(Integer const& integer) const
{
return myInt < integer.myInt;
}
Consider the following class that wraps a container and type-erases its type:
class C final {
struct B {
virtual bool empty() const noexcept = 0;
};
template<class T, class A>
struct D: public B {
// several constructors aimed to
// correctly initialize the underlying container
bool empty() const noexcept override { return v.empty(); }
private:
std::vector<T, A> v;
};
// ...
public:
//...
bool operator==(const C &other) const noexcept {
// ??
// would like to compare the underlying
// container of other.b with the one
// of this->b
}
private:
// initialized somehow
B *b;
};
I'd like to add the operator== to the class C.
Internally, it should simply invoke the same operator on the underlying containers, but I'm stuck on this problem, for I don't know how to do that.
The idea is that two instances of C are equal if the operator== of their underlying containers return true.
Whatever I've tried till now, I ever ended up being unable to get the type of one of the two underlying containers, mainly the one of other.
Is there an easy solution I can't see at the moment or I should give up?
Despite the good suggestion from juanchopanza, I found that, as far as the underlying containers represent the same concept (as an example, different specializations of a vector), maybe there is no need of a type-erased iterator.
Below it's a possible implementation that relies on the operator[] and the size member method:
#include <vector>
#include <cassert>
class Clazz final {
struct BaseContainer {
virtual std::size_t size() const noexcept = 0;
virtual int operator[](std::size_t) const = 0;
virtual void push_back(int) = 0;
};
template<class Allocator>
struct Container: public BaseContainer {
Container(Allocator alloc): v{alloc} { }
std::size_t size() const noexcept override { return v.size(); }
int operator[](std::size_t pos) const override { return v[pos]; }
void push_back(int e) override { v.push_back(e); }
private:
std::vector<int, Allocator> v;
};
public:
template<class Allocator = std::allocator<int>>
Clazz(const Allocator &alloc = Allocator{})
: container{new Container<Allocator>{alloc}} { }
~Clazz() { delete container; }
void push_back(int e) { container->push_back(e); }
bool operator==(const Clazz &other) const noexcept {
const BaseContainer &cont = *container;
const BaseContainer &oCont = *(other.container);
bool ret = (cont.size() == oCont.size());
for(std::vector<int>::size_type i = 0, s = cont.size(); i < s && ret; i++) {
ret = (cont[i] == oCont[i]);
}
return ret;
}
bool operator!=(const Clazz &other) const noexcept {
return !(*this == other);
}
private:
BaseContainer *container;
};
int main() {
Clazz c1{}, c2{}, c3{};
c1.push_back(42);
c2.push_back(42);
assert(c1 == c2);
assert(c1 != c3);
}
Open to criticism, hoping this answer can help other users. :-)
Assuming you wish to return false when the comparing two different containers, this should do the job (caution: untested):
class Container
{
struct Concept
{
virtual ~Concept() = default;
virtual Concept* clone() const = 0;
virtual bool equals(Concept const*) const = 0;
};
template<typename T>
struct Model final : Concept
{
Model(T t) : data{std::move(t)} {}
Model* clone() const override { return new Model{*this}; }
virtual bool equals(Concept const* rhs) const override
{
if (typeid(*this) != typeid(*rhs))
return false;
return data == static_cast<Model const*>(rhs)->data;
}
T data;
};
std::unique_ptr<Concept> object;
public:
template<typename T>
Container(T t) : object(new Model<T>{std::move(t)}) {}
Container(Container const& that) : object{that.object->clone()} {}
Container(Container&& that) = default;
Container& operator=(Container that)
{ object = std::move(that.object); return *this; }
friend bool operator==(Container const& lhs, Container const& rhs)
{ return lhs.object->equals(rhs.object.get()); }
};
I'm trying to implement a simple abstract syntax tree (AST) in C++ using the visitor pattern. Usually a visitor pattern does not handle return value. But in my AST there are expressions nodes which care about the return type and value of its children node. For example, I have a Node structure like this:
class AstNode
{
public:
virtual void accept(AstNodeVisitor&) = 0;
void addChild(AstNode* child);
AstNode* left() { return m_left; }
AstNode* right() { return m_right; }
...
private:
AstNode* m_left;
AstNode* m_right;
};
class CompareNode : public AstNode
{
public:
virtual void accept(AstNodeVisitor& v)
{
v->visitCompareNode(this);
}
bool eval(bool lhs, bool rhs) const
{
return lhs && rhs;
}
};
class SumNode : public AstNode
{
public:
virtual void accept(AstNodeVisitor& v)
{
v->visitSumNode(this);
}
int eval(int lhs, int rhs) const
{
return lhs + rhs;
}
};
class AstNodeVisitor
{
public:
...
bool visitCompareNode(CompareNode& node)
{
// won't work, because accept return void!
bool lhs = node.left()->accept(*this);
bool rhs = node.right()->accept(*this);
return node.eval(lhs, rhs);
}
int visitSumNode(Node& node)
{
// won't work, because accept return void!
int lhs = node.left()->accept(*this);
int rhs = node.right()->accept(*this);
return node.eval(lhs, rhs);
}
};
In this case both CompareNode and SumNode are binary operators but they rely on the return type of their children's visit.
As far as I can see to make it work, there are only 2 options:
accept can still return void, save the return value in a context object which is passed to each accept and visit function, and use them in the visit function, where I know what type to use. This should work but feels like a hack.
make AstNode a template, and accept function a none virtual, but return type depends on template parameter T.But if I do this, I no longer have a common AstNode* class and can't save any AstNode* in the children list.
for example:
template <typename T`>
class AstNode
{
public:
T accept(AstNodeVisitor&);
...
};
So is there a more elegant way to do this? This should be a fairly common problem for people implementing AST walking so I'd like to know what's the best practice.
Thanks.
The Visitor can have member that it can use to store result, something like:
class AstNodeVisitor
{
public:
void visitCompareNode(CompareNode& node)
{
node.left()->accept(*this); // modify b
bool lhs = b;
node.right()->accept(*this); // modify b
bool rhs = b;
b = node.eval(lhs, rhs);
}
void visitSumNode(Node& node)
{
node.left()->accept(*this); // modify n
int lhs = n;
node.right()->accept(*this); // modify n
int rhs = n;
n = node.eval(lhs, rhs);
}
private:
bool b;
int n;
};
You may also want to save the type of last result or use something like boost::variant.
template<class T> struct tag { using type=T; };
template<class...Ts> struct types { using type=types; }
template<class T>
struct AstVisitable {
virtual boost::optional<T> accept( tag<T>, AstNodeVisitor&v ) = 0;
virtual ~AstVisitable() {};
};
template<>
struct AstVisitable<void> {
virtual void accept( tag<void>, AstNodeVisitor&v ) = 0;
virtual ~AstVisitable() {};
};
template<class Types>
struct AstVisitables;
template<>
struct AstVisibables<types<>> {
virtual ~AstVisitables() {};
};
template<class T0, class...Ts>
struct AstVisitables<types<T0, Ts...>>:
virtual AstVisitable<T0>,
AstVisitables<types<Ts...>>
{
using AstVisitable<T0>::accept;
using AstVisitables<types<Ts...>>::accept;
};
using supported_ast_return_types = types<int, bool, std::string, void>;
class AstNode:public AstVisitables<supported_ast_return_types> {
public:
void addChild(AstNode* child);
AstNode* left() { return m_left.get(); }
AstNode* right() { return m_right.get(); }
private:
std::unique_ptr<AstNode> m_left;
std::unique_ptr<AstNode> m_right;
};
template<class types>
struct AstVisiablesFailAll;
template<>
struct AstVisiablesFailAll<> {
virtual ~AstVisiablesFailAll() {};
};
template<class T>
struct AstVisitableFailure : virtual AstVisitable<T> {
boost::optional<T> accept( tag<T>, AstNodeVisitor& ) override {
return {};
}
};
template<>
struct AstVisitableFailure<void> : virtual AstVisitable<void> {
void accept( tag<void>, AstNodeVisitor& ) override {
return;
}
};
template<class T0, class...Ts>
struct AstVisitablesFailAll<types<T0, Ts...>>:
AstVisitableFailure<T0>,
AstVisitableFailAll<types<Ts...>>
{
using AstVisitableFailure<T0>::accept;
using AstVisitableFailAll<types<Ts...>>::accept;
};
So now you can boost::optional<bool> lhs = node.left()->accept( tag<bool>, *this );, and from the state of lhs know if the left node can be evaluated in a bool context.
SumNode looks like this:
class SumNode :
public AstNode,
AstVisiablesFailAll<supported_ast_return_types>
{
public:
void accept(tag<void>, AstNodeVisitor& v) override
{
accept(tag<int>, v );
}
boost::optional<int> accept(tag<int>, AstNodeVisitor& v) override
{
return v->visitSumNode(this);
}
int eval(int lhs, int rhs) const {
return lhs + rhs;
}
};
and visitSumNode:
boost::optional<int> visitSumNode(Node& node) {
// won't work, because accept return void!
boost::optional<int> lhs = node.left()->accept(tag<int>, *this);
boost::optional<int> rhs = node.right()->accept(tag<int>, *this);
if (!lhs || !rhs) return {};
return node.eval(*lhs, *rhs);
}
The above assumes that visiting a+b in a void context is acceptable (like in C/C++). If it isn't, then you need a means for void visit to "fail to produce a void".
In short, accepting requires context, which also determines what type you expect. Failure is an empty optional.
The above uses boost::optional -- std::experimental::optional would also work, or you can roll your own, or you can define a poor man's optional:
template<class T>
struct poor_optional {
bool empty = true;
T t;
explicit operator bool() const { return !empty; }
bool operator!() const { return !*this; }
T& operator*() { return t; }
T const& operator*() const { return t; }
// 9 default special member functions:
poor_optional() = default;
poor_optional(poor_optional const&)=default;
poor_optional(poor_optional const&&)=default;
poor_optional(poor_optional &&)=default;
poor_optional(poor_optional &)=default;
poor_optional& operator=(poor_optional const&)=default;
poor_optional& operator=(poor_optional const&&)=default;
poor_optional& operator=(poor_optional &&)=default;
poor_optional& operator=(poor_optional &)=default;
template<class...Ts>
void emplace(Ts&&...ts) {
t = {std::forward<Ts>(ts)...};
empty = false;
}
template<class...Ts>
poor_optional( Ts&&... ts ):empty(false), t(std::forward<Ts>(ts)...) {}
};
which sucks, because it constructs a T even if not needed, but it should sort of work.
For completion sake I post the template version that is mentioned by the OP
#include <string>
#include <iostream>
namespace bodhi
{
template<typename T> class Beignet;
template<typename T> class Cruller;
template<typename T> class IPastryVisitor
{
public:
virtual T visitBeignet(Beignet<T>& beignet) = 0;
virtual T visitCruller(Cruller<T>& cruller) = 0;
};
template<typename T> class Pastry
{
public:
virtual T accept(IPastryVisitor<T>& visitor) = 0;
};
template<typename T> class Beignet : public Pastry<T>
{
public:
T accept(IPastryVisitor<T>& visitor)
{
return visitor.visitBeignet(*this);
}
std::string name = "Beignet";
};
template<typename T> class Cruller : public Pastry<T>
{
public:
T accept(IPastryVisitor<T>& visitor)
{
return visitor.visitCruller(*this);
}
std::string name = "Cruller";
};
class Confectioner : public IPastryVisitor<std::string>
{
public:
virtual std::string visitBeignet(Beignet<std::string>& beignet) override
{
return "I just visited: " + beignet.name;
}
virtual std::string visitCruller(Cruller<std::string>& cruller) override
{
return "I just visited: " + cruller.name;
}
};
}
int main()
{
bodhi::Confectioner pastryChef;
bodhi::Beignet<std::string> beignet;
std::cout << beignet.accept(pastryChef) << "\n";
bodhi::Cruller<std::string> cruller;
std::cout << cruller.accept(pastryChef) << "\n";
return 0;
}
Every pastry is a node and every visitor can implement its accepted return type. Having multiple visitor could visit the same pastry.
I'm attempting to re-create the any that is found in Boost::any and I have built the three classes, however, whenever I come to reinterpret_cast for the value that is given, the output is completely different and just throws out garbage. Here is my code below:
namespace Types {
class PlaceMaker {
public:
PlaceMaker() { };
virtual ~PlaceMaker()
{
}
virtual PlaceMaker * clone()
{
return 0;
}
virtual const std::type_info & type() const = 0;
protected:
};
template<typename T>
class holder : public PlaceMaker {
public:
holder(const T & value)
: held(value)
{
}
virtual const std::type_info & type() const
{
return typeid(T);
}
virtual PlaceMaker * clone() const
{
return new holder(held);
}
T retrunHeld() const {
return held;
}
public:
T held;
//holder &operator=(const holder &) const = 0;
holder & operator=(const holder &) { }
};
class Any : PlaceMaker {
public:
Any() : maker(0) { };
template<typename ValueType>
Any(const ValueType & value)
: maker(new holder<ValueType>(value))
{
}
Any(const Any & other)
: maker(other.maker ? other.maker->clone() : 0)
{
}
Any& swap(Any &rhs) {
std::swap(maker, rhs.maker);
return *this;
}
template<typename ValueType>
Any & operator=(const ValueType & rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any & operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !maker;
}
const std::type_info & type() const
{
return maker ? maker->type() : typeid(void);
}
template<typename T>
T& cast() {
T* r = reinterpret_cast<T*>(maker);
return *r;
}
public:
PlaceMaker * maker;
};
In main I have the following:
int main() {
Types::Any a = 10;
std::cout << a.cast<int>();
}
// output: 96458224
Could anyone tell me as to where I'm going wrong?
Thanks
You're casting a Holder* to a T*. Given that Holder has virtual functions in it, that means you're gonna be looking at the vtable, not the T itself.