Tải bản đầy đủ (.pdf) (6 trang)

HandBooks Professional Java-C-Scrip-SQL part 64 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (20.47 KB, 6 trang )

std::sort(properties.begin(),properties.end());
std::for_each(
properties.begin(),
properties.end(),
print_names);
std::cout << "\n";
std::cout <<
boost::any_cast<std::string>(properties[0].value()) << "\n";
std::cout <<
boost::any_cast<int>(properties[1].value()) << "\n";
std::cout <<
boost::any_cast<double>(properties[2].value()) << "\n";
}
Notice that we didn't have to explicitly create the anys needed for property's
constructor. That's because any's converting constructor isn't explicit. Although
constructors taking one argument should typically be declared explicit, any is an
exception to the rule. Running the program gives us this output.
Example of using any for storing properties.
A
B
C
Thirty something
30
3.1415
In this example, because the container was sorted, we retrieved the properties by
index, and as we knew their respective types beforehand, we didn't need a
try/catch block for the retrieval. When retrieving the value of an instance of
any, pass the any by const reference to any_cast if a failure indicates a real
error.
std::string s=boost::any_cast<std::string>(a);
When a failure is not necessarily an error, pass the any by pointer.


std::string* ps=boost::any_cast<std::string>(&a);
The different styles of getting the stored value differ not only in semantics, but also
how they return the stored value. If you pass a pointer argument, you get a pointer
to the stored value; if you pass a const reference argument, you get a copy of the
value.
If the value type is expensive to copy, pass the any by pointer to avoid copying the
value.
There's More to any
There are a few more member functions provided by any, such as testing whether
an instance of any is empty or not, and swapping the values of two instances of
any. The following example shows how to use them.
#include <iostream>
#include <string>
#include "boost/any.hpp"
int main() {
std::cout << "Example of using any member functions\n\n";
boost::any a1(100);
boost::any a2(std::string("200"));
boost::any a3;
std::cout << "a3 is ";
if (!a3.empty()) {
std::cout << "not ";
}
std::cout << "empty\n";
a1.swap(a2);
try {
std::string s=boost::any_cast<std::string>(a1);
std::cout << "a1 contains a string: " << s << "\n";
}
catch(boost::bad_any_cast& e) {

std::cout << "I guess a1 doesn't contain a string!\n";
}
if (int* p=boost::any_cast<int>(&a2)) {
std::cout << "a2 seems to have swapped contents with a1: "
<< *p << "\n";
}
else {
std::cout << "Nope, no int in a2\n";
}
if (typeid(int)==a2.type()) {
std::cout << "a2's type_info equals the type_info of int\n";
}
}
Here's the output from running the program.
Example of using any member functions
a3 is empty
a1 contains a string: 200
a2 seems to have swapped contents with a1: 100
a2's type_info equals the type_info of int
Let's examine that code more closely. To test whether an instance of any contains
a value, we called the member function empty. We tested the any a3 like this.
std::cout << "a3 is ";
if (!a3.empty()) {
std::cout << "not ";
}
std::cout << "empty\n";
Because we default constructed a3, a3.empty() returns TRue. The next thing
is to swap the contents of a1 with a2. You may wonder why you'd want to swap
their contents. One plausible scenario is when the identities of the any instances
are important (swap only exchanges the contained values). Another reason is to

avoid copying when you don't need to keep the original value.
a1.swap(a2);
Finally, we use the member function type, which returns a const
std::type_ info&, to test if the contained value is of the type int.
if (typeid(int)==a2.type()) {
Note that if an any stores a pointer type, that is reflected in the returned
std::type_info.
Storing Pointers in any
Often, the test for empty is enough to know whether the object really contains
something valid. However, if an any might hold a pointer, be extra careful to test
the pointer before trying to dereference it. Simply testing whether the any is
empty is not enough, because an any is not considered to be empty when it holds a
pointer, even if that pointer is null.
boost::any a(static_cast<std::string*>(0));
if (!a.empty()) {
try {
std::string* p=boost::any_cast<std::string*>(a);
if (p) {
std::cout << *p;
}
else {
std::cout << "The any contained a null pointer!\n";
}
}
catch(boost::bad_any_cast&) {}
}
A Better WayUsing shared_ptr
Another complication when storing raw pointers in any is the destruction
semantics. The any class accepts ownership of the value it stores, because it keeps
an internal copy of the value, which is destroyed together with the any. However,

destroying a raw pointer doesn't invoke delete or delete[] on it! It only
reclaims the memory occupied by the pointer. This makes storing a raw pointer in
any problematic, so it's a good idea to use smart pointers instead. Indeed, using
smart pointers (see "Library 1: Smart_ptr 1") is an ideal way to store a pointer to
data in an any. This solves the problem of making sure that the memory
associated with a contained pointer is properly deleted. When the smart pointer is
destroyed, it takes appropriate action to ensure the memory and any data in it are
properly destroyed. By contrast, note that std::auto_ptr is not appropriate.
This is because auto_ptr doesn't have normal copy semantics; accessing the
value in an any would transfer ownership of the memory and any data in it from
the any to the returned auto_ptr.
Consider the following code.
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include "boost/any.hpp"
#include "boost/shared_ptr.hpp"
First, we'll define two classes, A and B, each with operations is_virtual, which
is virtual, and not_virtual, which is not virtual (had it been virtual, the name
would be an extremely bad choice). We want to store objects of these types in
anys.
class A {
public:
virtual ~A() {
std::cout << "A::~A()\n";
}
void not_virtual() {
std::cout << "A::not_virtual()\n";
}

virtual void is_virtual () {
std::cout << "A:: is_virtual ()\n";
}
};
class B : public A {
public:
void not_virtual() {
std::cout << "B::not_virtual()\n";
}
virtual void is_virtual () {
std::cout << "B:: is_virtual ()\n";
}
};
Let's now define a free function, foo, which accepts an argument that is a
reference to any and that examines the any using any_casts to the types that
the function knows how to handle. If there's no match, the function simply ignores
the any and returns. It tests for the types shared_ptr<A> and
shared_ptr<B>, respectively, and calls is_virtual (the virtual function)
and not_virtual on them.
void foo(boost::any& a) {
std::cout << "\n";
// Try boost::shared_ptr<A>
try {
boost::shared_ptr<A> ptr=
boost::any_cast<boost::shared_ptr<A> >(a);

×