.dp-highlighter { font-family: "Consolas", "Monaco", "Courier New", Courier, monospace; font-size: 12px; background-color: #E7E5DC; width: 99%; overflow: auto; margin: 18px 0 18px 0 !important; padding-top: 1px; /* adds a little border on top when controls are hidden */ } /* clear styles */ .dp-highlighter ol, .dp-highlighter ol li, .dp-highlighter ol li span { margin: 0; padding: 0; border: none; } .dp-highlighter a, .dp-highlighter a:hover { background: none; border: none; padding: 0; margin: 0; } .dp-highlighter .bar { padding-left: 45px; } .dp-highlighter.collapsed .bar, .dp-highlighter.nogutter .bar { padding-left: 0px; } .dp-highlighter ol { list-style: decimal; /* for ie */ background-color: #fff; margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */ padding: 0px; color: #5C5C5C; } .dp-highlighter.nogutter ol, .dp-highlighter.nogutter ol li { list-style: none !important; margin-left: 0px !important; } .dp-highlighter ol li, .dp-highlighter .columns div { list-style: decimal-leading-zero; /* better look for others, override cascade from OL */ list-style-position: outside !important; border-left: 3px solid #6CE26C; background-color: #F8F8F8; color: #5C5C5C; padding: 0 3px 0 10px !important; margin: 0 !important; line-height: 14px; } .dp-highlighter.nogutter ol li, .dp-highlighter.nogutter .columns div { border: 0; } .dp-highlighter .columns { background-color: #F8F8F8; color: gray; overflow: hidden; width: 100%; } .dp-highlighter .columns div { padding-bottom: 5px; } .dp-highlighter ol li.alt { background-color: #FFF; color: inherit; } .dp-highlighter ol li span { color: black; background-color: inherit; } /* Adjust some properties when collapsed */ .dp-highlighter.collapsed ol { margin: 0px; } .dp-highlighter.collapsed ol li { display: none; } /* Additional modifications when in print-view */ .dp-highlighter.printing { border: none; } .dp-highlighter.printing .tools { display: none !important; } .dp-highlighter.printing li { display: list-item !important; } /* Styles for the tools */ .dp-highlighter .tools { padding: 3px 8px 3px 10px; font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: #f8f8f8; padding-bottom: 10px; border-left: 3px solid #6CE26C; } .dp-highlighter.nogutter .tools { border-left: 0; } .dp-highlighter.collapsed .tools { border-bottom: 0; } .dp-highlighter .tools a { font-size: 9px; color: #a0a0a0; background-color: inherit; text-decoration: none; margin-right: 10px; } .dp-highlighter .tools a:hover { color: red; background-color: inherit; text-decoration: underline; } /* About dialog styles */ .dp-about { background-color: #fff; color: #333; margin: 0px; padding: 0px; } .dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; } .dp-about td { padding: 10px; vertical-align: top; } .dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; } .dp-about .title { color: red; background-color: inherit; font-weight: bold; } .dp-about .para { margin: 0 0 4px 0; } .dp-about .footer { background-color: #ECEADB; color: #333; border-top: 1px solid #fff; text-align: right; } .dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; color: #333; width: 60px; height: 22px; } /* Language specific styles */ .dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; } .dp-highlighter .string { color: blue; background-color: inherit; } .dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; } .dp-highlighter .preprocessor { color: gray; background-color: inherit; }

Tuesday, November 11, 2008

boost::any (2) - storing pointers in boost::any

We know that we can retrieve the value stored in a boost::any using one of the two overloaded boost::any_cast by either passing our any by reference or as a pointer. What if we store a pointer in boost::any?

The following example assumes the declaration from the previous boost::any(1) post:

int main()
{
typedef std::vector<boost::any> MixedContainer_t;
MixedContainer_t mixedContainer;

A* aPtr1 = new A(2);
A* aPtr2 = new A(3);

mixedContainer.push_back(aPtr1);
mixedContainer.push_back(aPtr2);

//would not work. What is stored at front() is a pointer to A
//and not an object of type A.
if(A* a = boost::any_cast<A> (&mixedContainer.front()))
a->print();

//we can even confirm it by testing the types
if(typeid(A*) == mixedContainer.back().type())
{
std::cout << "object at front() is a pointer to A" << std::endl;
}
//to get a pointer to it, we need to retrieve a A**, and pass
//the type of object we think stored at front as A*
if(A** a = boost::any_cast<A*> (&mixedContainer.front()))
{
std::cout << "pointer-> ";
(*a)->print();
}

}


Storing pointers in boost::any is problematic, because boost::any stores only a value of the pointer, and when the boost::any is destroyed, the only memory that is released is that occupied by the pointer, and not the memory it points to. That is, delete or delete[] is not called. What to do? Use smart pointers. As with standard containers, avoid using auto_ptr because of its 'weird' copy semantics.

#include <iostream>
#include <vector>
#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>


class A
{
int value_;
public:
A(int value) : value_(value) {}
void print() const {std::cout << "A's value: " << value_ << std::endl;}
~A() {std::cout << "A(" << value_ <<") destructor" << std::endl; }
};

class B
{
int value_;
public:
B(int value) : value_(value) {}
void print() const {std::cout << "B's value: " << value_ << std::endl;}
~B() {std::cout << "B(" << value_ <<") destructor" << std::endl; }
};

int main()
{
typedef std::vector<boost::any> MixedContainer_t;
MixedContainer_t mixedContainer;

boost::shared_ptr<A> aPtr0(new A(1));
A* aPtr1 = new A(2);
A* aPtr2 = new A(3);

mixedContainer.push_back(aPtr0);
mixedContainer.push_back(aPtr1);
mixedContainer.push_back(aPtr2);

//and to retrieve the value from shared Ptr is simple
try
{
boost::shared_ptr<A> ptr = boost::any_cast<boost::shared_ptr<A> > (mixedContainer.front());
ptr->print();

}
catch(boost::bad_any_cast& bac)
{
bac.what();
}
//only the destructor of the A pointed to by shared_ptr is printed.
}

No comments :