发信人: flier (小海 (:好日子不多了:)), 信区: Programming 标 题: boost::any 发信站: BBS 水木清华站 (Mon May 13 12:02:24 2002)
我来抛砖,有人跟进吗?:)
boost::any
boost::any是一个很有趣的类,刚刚开始我还以为其就是一个variant类型, 能够将任意类型值保存进去,能够以任意类型值读出来,不过我错了 :( boost::any的作者认为,所谓generic type有三个层面的解释方法: 1.类似variant类型那样任意进行类型转换,可以保存一个(int)5进去, 读一个(string)"5"出来。Win下面的VARIANT类型是以一个巨大的 union实现的类似功能,使用灵活但效率较低 2.区别对待包含值的类型,保存一个(int)5进去,不会被隐式转换为 (string)'5'或者(double)5.0,这样效率较高且类型安全, 不必担心ambiguous conversions 3.对包含值类型不加区别,例如把所有保存的值强制转换为void *保存 读取时再有程序员判断其类型。这样效率虽最高但无法保证类型安全 boost::any就选择了第二层面的设计思路,它允许用户将任意类型值保存 进一个any类型变量,但内部并不改变值的类型,并提供方法让用户在使用时 主动/被动进行类型判断。
在实现方面,boost::any使用两层内部类placeholder和holder保存 实际类型的值。类placeholder只是一个接口,模板类holder是特定类型 的实现。其中type()方法获取实际值类型,即typeid(ValueType); clone()方法获取值的拷贝return new holder(held); virtual const std::type_info & type() const virtual placeholder * clone() const 其值的类型信息不象Win的VARIANT那样以专门的字段保存, 而是通过模板参数形式静态保存。这样效率更高(仅在编译期),
通用性更强(任何类型都可以,真正any)但灵活性不如VARIANT 在进行拷贝构造/赋值/swap时,都直接将整个placeholder换掉, 这样可以保证值类型的延续性。
在使用方面,提供了主动/被动进行类型检测的方法。 可以使用any::type()方法主动检测值类型 bool is_int(const boost::any & operand) { return operand.type() == typeid(int); } 也可以通过any_cast函数被动进行检测。此函数与C++中的*_cast 系列关键字有相同的语法规范,尝试进行类型转换,如类型不匹配则对 指针转换返回NULL,对引用转换抛出boost::bad_any_cast异常 在实现方面,boost::any使用两层内部类placeholder和holder保存 实际类型的值。类placeholder只是一个接口,模板类holder是特定类型 的实现。其中type()方法获取实际值类型,即typeid(ValueType); clone()方法获取值的拷贝return new holder(held); virtual const std::type_info & type() const virtual placeholder * clone() const 其值的类型信息不象Win的VARIANT那样以专门的字段保存, 而是通过模板参数形式静态保存。这样效率更高(仅在编译期),
通用性更强(任何类型都可以,真正any)但灵活性不如VARIANT 在进行拷贝构造/赋值/swap时,都直接将整个placeholder换掉, 这样可以保证值类型的延续性。
在使用方面,提供了主动/被动进行类型检测的方法。 可以使用any::type()方法主动检测值类型 bool is_int(const boost::any & operand) { return operand.type() == typeid(int); } 也可以通过any_cast函数被动进行检测。此函数与C++中的*_cast 系列关键字有相同的语法规范,尝试进行类型转换,如类型不匹配则对 指针转换返回NULL,对引用转换抛出boost::bad_any_cast异常 boost::any str = string("12345"); try { cout << boost::any_cast<int>(str) << endl; } catch(boost::bad_any_cast e) { cerr << e.what() << endl; }
在应用方面,any类型适合于类型不同但使用相关的值。如C++的... 形式的函数参数本事不是类型安全的,可以通过vector<any>改造之 然后在使用时检测类型是否匹配,如可改造printf为 void safe_printf(const char *format, const vector<any>& params) { int index = 0; for(const char *pch = format; *pch; pch++) { switch(*pch) { case '%': { switch(*++pch) { case 'i': case 'd': { if(params[index].type() == typeid(int) || params[index].type() == typeid(short)) { ... } else throw ... } } } case '\': { ... } default: { { switch(*++pch) { case 'i': case 'd': { if(params[index].type() == typeid(int) || params[index].type() == typeid(short)) { ... } else throw ... } } } case '\': { ... } default: { putchar(*pch); } } } }
附:boost::any.hpp #ifndef BOOST_ANY_INCLUDED #define BOOST_ANY_INCLUDED
// what: variant type boost::any // who: contributed by Kevlin Henney, // with features contributed and bugs found by // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran // when: July 2001 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
#include <algorithm> #include <typeinfo>
#include "boost/config.hpp"
~any() { delete content; }
public: // modifiers
any & swap(any & rhs) { std::swap(content, rhs.content); return *this; }
template<typename ValueType> any & operator=(const ValueType & rhs) { any(rhs).swap(*this); return *this; }
any & operator=(const any & rhs) { ~any() { delete content; }
public: // modifiers
any & swap(any & rhs) { std::swap(content, rhs.content); return *this; }
template<typename ValueType> any & operator=(const ValueType & rhs) { any(rhs).swap(*this); return *this; }
any & operator=(const any & rhs) { any(rhs).swap(*this); return *this; }
public: // queries
bool empty() const { return !content; }
const std::type_info & type() const { return content ? content->type() : typeid(void); }
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: // types #else public: // types (public so any_cast can be non-friend) #endif
any(rhs).swap(*this); return *this; }
public: // queries
bool empty() const { return !content; }
const std::type_info & type() const { return content ? content->type() : typeid(void); }
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: // types #else public: // types (public so any_cast can be non-friend) #endif
holder(const ValueType & value) : held(value) { }
public: // queries
virtual const std::type_info & type() const { return typeid(ValueType); }
virtual placeholder * clone() const {
return new holder(held); }
public: // representation
ValueType held;
holder(const ValueType & value) : held(value) { }
public: // queries
virtual const std::type_info & type() const { return typeid(ValueType); }
virtual placeholder * clone() const {
return new holder(held); }
public: // representation
ValueType held;
virtual const char * what() const throw() { return "boost::bad_any_cast: " "failed conversion using boost::any_cast"; } };
template<typename ValueType> ValueType * any_cast(any * operand) { return operand && operand->type() == typeid(ValueType) ? &static_cast<any::holder<ValueType> *>(operand->content)->held : 0; }
template<typename ValueType> const ValueType * any_cast(const any * operand) { return any_cast<ValueType>(const_cast<any *>(operand)); }
template<typename ValueType>
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. // // Permission to use, copy, modify, and distribute this software for any // purpose is hereby granted without fee, provided that this copyright and // permissions notice appear in all copies and derivatives. // // This software is provided "as is" without express or implied warranty.
#endif
-- . 生命的意义在于 /\ ____\ /\_ \ /\_\ . . 希望 \ \ \___/_\/\ \ \/_/__ __ _ _★ . . 工作 \ \ ____\\ \ \ /\ \ /'__`\ /\`'_\ . . 爱你的人 \ \ \___/ \ \ \___\ \ \/\ __//\ \ \/ . . 和你爱的人 \ \___\ \ \_____\ \__\ \____\ \ \_\ . . …… \/___/ \/_____/\/__/\/____/ \/_/ @126.com .
※ 修改:·flier 於 May 13 12:03:25 修改本文·[FROM: 202.114.32.217] ※ 来源:·BBS 水木清华站 bbs.edu.cn·[FROM: 202.114.32.217]

|