C++ 我应该什么时候使用std::any
因为C++17C++ 我应该什么时候使用std::any,c++,c++17,stdany,C++,C++17,Stdany,因为C++17std::any被引入。现在可以编写这样的代码了 #include <iostream> #include <any> #include <string> int main () { const double d = 1.2; std::any var = d; const std::string str = "Hello World"; var = str; } #包括 #包括何时使用 void*作为一种极不
std::any
被引入。现在可以编写这样的代码了
#include <iostream>
#include <any>
#include <string>
int main () {
const double d = 1.2;
std::any var = d;
const std::string str = "Hello World";
var = str;
}
#包括
#包括何时使用
void*
作为一种极不安全的模式,在一些有限的用例中,std::any
添加了类型安全性,这就是为什么它有一些真实的用例
一些可能性:
- 在库中-当库类型必须在不知道
可用类型集。
- 解析文件-如果您确实无法指定支持的
类型。
- 消息传递。
- 使用脚本语言进行绑定。
- 为脚本语言实现解释器
- 用户界面-控件可能包含任何内容
- 编辑器中的实体
()
我将其概括为经典的“无法避免时使用”
我只能想到动态类型脚本语言的非性能关键型实现来表示脚本世界中的变量,但即使是这样,也需要进行扩展(对于解析器和运行时都不需要)
对于从解析器(例如)到库API(例如)的所有其他东西,通常会有一个更快/更好/更具体的替代方案,因为真正“有什么”的东西很少,大多数都比这更具体
std::variant
和/或std::optional
用于“几乎任何值”
std::packaged_task
/std::function
+lambdas表示“带参数的回调”,这在C API中是void*
的情况
- 等等
具体地说,我不会盲目地用它来代替
void*
,因为它是堆上的内存,这对高性能代码来说可能是致命的。它用于Wt,为用户提供非模板接口
对于内置类型和Wt类型,存在到字符串的转换,您可以通过专门化来注册其他转换。这允许任何内容在表中显示为条目,视图类不必知道它们所显示的类型。std::any
是词汇表类型。当你需要存储一些东西的时候,你可以使用它
it有许多“第一级”用途:
当与本身具有此类类型的脚本语言交互时,这是一种自然的适合
当您有一个具有高度多态性内容的属性树,并且树的结构与树的生产者和消费者解耦时
当替换通过中间层传递的void*
数据块的等价物时,中间层实际上并不关心它所承载的内容
在其他情况下,它也可以用作构建块。例如,std::function
可以选择将其值存储在std::any
中:
template<class R, class...Args>
struct func<R(Args...)> {
mutable std::any state;
R(*f)(std::any& state, Args&&...) = nullptr;
template<class T>
void bind(T&& t) {
state = std::forward<T>(t);
f = [](std::any& state, Args&&...args)->R {
return std::any_cast<T&>(state)(std::forward<Args>(args)...);
};
}
R operator()(Args...args)const {
return f(state, std::forward<Args>(args)...);
}
};
模板
结构函数{
可变std::任何状态;
R(*f)(标准::任何和状态,参数和…)=nullptr;
模板
无效绑定(T&T){
状态=标准::正向(t);
f=[](std::any&state,Args&&…Args)->R{
返回std::any_cast(state)(std::forward.如果您使用std::any
来混淆代码,那么请确保它违反了最小惊奇规则。如果您将其用作更安全的void*
(请参阅链接到的文章T.C.)使用std::any
在过去您可能会使用void*
的地方。也就是说,理想情况下,几乎没有任何地方。它与工厂模式一起好吗?“如果您确实无法指定支持的类型。”表示阅读“任何”如果我不知道std::any中包含了什么,我就不知道如何处理这些数据。如果我知道如何处理这些数据,我就知道可能存储的类型的列表。这就是std::variant。我不能理解重点…你能解释一下吗?@Klaus,如果解析代码是通用的并且可能不知道所有类型都是编译时类型(或者支持的类型是动态的,或者您不想创建依赖关系)。“为脚本语言实现解释器”是一个很好的例子。尤其是与“与脚本语言绑定”相结合。我发现在实现受约束的Python解释器时使用std::any
非常方便。@Klaus:用例是当一些代码知道存储的类型,但该代码不负责整个生命周期(可能包括复制)该规范允许小对象优化IUC。@StoryTeller-我更新了答案,其中有一个指向该问题的链接。那里有每个编译器的详细信息。请看一看。你能发布一个指向使用这些特性的代码示例的链接吗?我没有example to hand.你可以在Wt源代码中查找它是如何处理的,比如说,WDateTime
tbh,这种类型不应该被称为std::any
。它是…std::some(thing?
@swift你必须与…嗯,没有人,因为它没有改变。但肯定不是我。