2012-02-02 119 views
8

我需要将any变量转换为原始类型。 我需要这样做:Boost.Any获得原始类型

int i = 10; 
any a(i); 
int& i2 = any_cast<int &>(a); 

但我想,在any变量的类型存储。而我写这篇文章:

int i = 10; 
any a(i); 
a::type_value& i2 = any_cast<a::type_value &>(a); // there is no actually type_value 

我怎么能这样做呢?或者我如何从any变量中提取原始类型? Boost.variant也很方便。

如果我不能这样做,那么我有另一个问题,C++技术和库可以存储什么,并通过函数获取类型来解决这个问题?

+1

您只需使用Boost.Any就可以做到这一点,所以使用Boost.Variant将会是最基本的答案。 – ildjarn 2012-02-02 00:17:24

+2

*为什么*你需要这样做? – GManNickG 2012-02-02 00:25:30

回答

15

C++是一个静态键入语言。 boost::any的类型是运行时的值;任何特定的any都可以有任何类型。这是有点点。

没有any::type_value,因为那必须是编译时间的值。而any是一个运行时构造。

考虑一下:

void TakeAnAny(boost::any a) 
{ 
    a::type_value& i2 = any_cast<a::type_value &>(a); 
} 

是什么类型any::type_value?用TakeAnAny虚拟任何类型是合法的。没有一个编译时类型可以减少到any::type_value。因此,编译器无法确定类型。由于C++是静态类型的,因此你会被弄糊涂。

任何类型的最终目的是擦除。我有一些价值。我想把它传递给其他功能。这个过程将经过几个不同的通信层。但我不一定希望所有这些不同的图层都知道我正在使用哪种类型的图层。我只需要我自己和我的预定目的地知道类型。所以你坚持在any,你很好。其他人都看到了any,你们都知道它的包装。

此过程仅适用于源和目标都知道值的实际类型。如果你不知道类型,那么你不应该使用anyany的目的是没有一个功能坐在那里,并将其投掷到一堆可能的类型(这就是boost::variant是什么)。目的是从函数的签名中删除该类型。

这允许像通用消息和信号的东西。您使用系统注册一些事件处理程序。您触发以any作为参数的事件。发起事件的人知道“MouseClick”事件总是以vec2作为参数。因此,每个“MouseClick”处理程序都将其转换为vec2。 “KeyPress”活动可能会通过int32_t。所以这些处理程序将其转换为该类型。等等。每个人都知道它实际需要什么类型。

这曾经与void*完成。存在的问题是您拥有所有权问题(any是一个值,而void*是一个指针)。此外,void*是这样删除类型,无法检查,看看你的演员是否正确。 any实际上只是一种类型&价值安全void*;它可以防止你输入错误的类型。

你真的不想要any。您的使用案例似乎也不需要variant。你似乎想要的是模板。这是一种不同的东西,它可以让你做你想做的事:有一个可以使用任何特定类型的函数,但仍然能够确切地知道该类型是什么。

当然,模板有其自身的局限性。

1

您可以使用地图std::type_infostd::function<void(boost::any const&)>对象来处理,你知道的类型,你要处理的:你会使用a.type()定位在地图中的条目,并调用相应的函数,它会知道如何处理这个论点。

+2

如果有人知道他们将要处理的类型,那么为什么要使用Boost.Any而不是Boost.Variant? – ildjarn 2012-02-02 00:31:07

+1

它似乎是一个更简单的类型传递。此外,可能有一些接口将'boost :: any'作为参数,并最终调用一个函数,其中'boost :: any'以某种形式返回。例如,似乎将一个'boost :: any'附加到一个对象以保存任意信息是合理的,并且该类的用户可能非常清楚他可能附加哪些类型。 – 2012-02-02 00:33:47

+0

鉴于_that特定情景_然后我同意'boost ::任何<>'可能是适当的;毕竟,图书馆确实存在的原因。但不知何故,我怀疑OP是在这种特定的情况下,我仍然会投票给Boost.Variant,除非OP有一个不可行的具体原因。 ; - ] – ildjarn 2012-02-02 00:46:27