any是个很短小的类, 代码加上空行和说明也就187行,但很有意思。它的主要作用是定义一个变量来存放任意类型数据。 这方面我们多少有些经验,MS的tagVARIANT结构相信不少人都用过。tagVARIANT能用,有用,但不好用,通过variant_t包装后感觉才好一些,但仍旧有些别扭。any类让人感到比较自然,建议大家使用,下面先看一看示例:
最常见的用法
另一种用法, 定义名字-值对(name-value pairs)
基于回调函数的运行时多态
若是自已考虑实现一个这样的类,最开始可能会想到union方式的实现,tagVARIANT就用 这种方法实现。对模板熟悉的人则会第一时间考虑到使用模板,对于第一感,这里给出一段代码, 此段代码摘至 Conversations: I'd Hold Anything for You (Jim Hyslop and Herb Sutter) 此文介绍了any。文中的Guru的一句台词就是"You need any.",懒得写一段了,呵呵。
但是,一个此类变量会在其生命周期内改变值(在脚本语言多有这样的体会),这种写法做出来的是无法完成的。
那any类是如何实现的? 还是模板,但多了一些技巧。
前面的例子让我们看到,直接用模板是不现实的,那么我们需要一个间接层。第一点便是要避免 ValueType value_ 这种形式的代码,这好办,在类中加入一个纯虚基类;第二点,写出any a(100) 形式的表达式,呵,模板的实参推导(deduction)可以帮忙。去掉类型信息,去掉any_cast,去掉赋值(虽然我刚才提到这一点)...,我给出一个更加短小的简化版本的any(只有三十几行代码),大家可以看一看是如何实现的。当然看完了这个应该去any.hpp看一看,以防被误导 :P
最常见的用法
any a(100);
cout << any_cast<int>(a) << " : " << a.type().name() << endl;
any b(string("hello"));
cout << any_cast<string>(b) << " : " << b.type().name() << endl;
b = a;
cout << any_cast<int>(a) << " : " << b.type().name() << endl;
cout << any_cast<int>(a) << " : " << a.type().name() << endl;
any b(string("hello"));
cout << any_cast<string>(b) << " : " << b.type().name() << endl;
b = a;
cout << any_cast<int>(a) << " : " << b.type().name() << endl;
另一种用法, 定义名字-值对(name-value pairs)
struct property
{
property();
property(const std::string &, const boost::any &);
std::string name;
boost::any value;
};
typedef std::list<property> properties;
{
property();
property(const std::string &, const boost::any &);
std::string name;
boost::any value;
};
typedef std::list<property> properties;
基于回调函数的运行时多态
class consumer
{
public:
virtual void notify(const any &) = 0;
};
{
public:
virtual void notify(const any &) = 0;
};
若是自已考虑实现一个这样的类,最开始可能会想到union方式的实现,tagVARIANT就用 这种方法实现。对模板熟悉的人则会第一时间考虑到使用模板,对于第一感,这里给出一段代码, 此段代码摘至 Conversations: I'd Hold Anything for You (Jim Hyslop and Herb Sutter) 此文介绍了any。文中的Guru的一句台词就是"You need any.",懒得写一段了,呵呵。
template <typename ValueType>
class multiType
{
ValueType value_;
public:
multiType(const ValueType &t) : value_(t) {}
operator ValueType() { return value_; }
};
class multiType
{
ValueType value_;
public:
multiType(const ValueType &t) : value_(t) {}
operator ValueType() { return value_; }
};
但是,一个此类变量会在其生命周期内改变值(在脚本语言多有这样的体会),这种写法做出来的是无法完成的。
那any类是如何实现的? 还是模板,但多了一些技巧。
前面的例子让我们看到,直接用模板是不现实的,那么我们需要一个间接层。第一点便是要避免 ValueType value_ 这种形式的代码,这好办,在类中加入一个纯虚基类;第二点,写出any a(100) 形式的表达式,呵,模板的实参推导(deduction)可以帮忙。去掉类型信息,去掉any_cast,去掉赋值(虽然我刚才提到这一点)...,我给出一个更加短小的简化版本的any(只有三十几行代码),大家可以看一看是如何实现的。当然看完了这个应该去any.hpp看一看,以防被误导 :P
class any
{
public:
template<typename _T>
any(const _T& value): _content(new holder<_T>(value))
{
}
~any()
{
delete _content;
}
class placeholder
{
};
public:
template<typename _T>
class holder: public placeholder
{
public:
holder(const _T& value): _held(value)
{
}
_T _held;
};
placeholder* _content;
};
int main()
{
any a(100);
cout << ((any::holder<int>*)(a._content))->_held << endl;
any b(string("string"));
cout << ((any::holder<string>*)(b._content))->_held << endl;
return 0;
}
{
public:
template<typename _T>
any(const _T& value): _content(new holder<_T>(value))
{
}
~any()
{
delete _content;
}
class placeholder
{
};
public:
template<typename _T>
class holder: public placeholder
{
public:
holder(const _T& value): _held(value)
{
}
_T _held;
};
placeholder* _content;
};
int main()
{
any a(100);
cout << ((any::holder<int>*)(a._content))->_held << endl;
any b(string("string"));
cout << ((any::holder<string>*)(b._content))->_held << endl;
return 0;
}