1. Trang chủ
  2. » Công Nghệ Thông Tin

O''''Reilly Network For Information About''''s Book part 64 doc

6 237 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 20,47 KB

Nội dung

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); . 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. 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. 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

Ngày đăng: 07/07/2014, 08:20