发信人: 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]