我什么时候应该使用std :: any

时间:2018-10-09 07:10:28

标签: c++ c++17 stdany

自从引入C ++ 17 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;
}

为变量var分配了一个双精度字,然后为该变量分配了一个std::string

为什么引入了std::any

我认为这违反了least astonishment rule,因为我很难想到一种情况,可以用这种情况更清楚地表达我喜欢表达的内容。

std::any有益的情况下,有人可以给我一个很好的例子。

https://gcc.godbolt.org/z/-kepOD

4 个答案:

答案 0 :(得分:6)

何时使用
void*作为具有某些有限用例的极其不安全的模式,std::any增加了类型安全性,这就是为什么它具有一些实际用例的原因。

一些可能性:

  • 在库中-当库类型必须在不知道 一组可用的类型。
  • 解析文件-如果您确实无法指定受支持的文件 类型。
  • 消息传递。
  • 使用脚本语言进行绑定。
  • 为脚本语言实现解释器
  • 用户界面-控件可能包含任何内容
  • 编辑器中的实体
    ref

答案 1 :(得分:2)

我将其概括为经典的“在无法避免时使用”。

我只能想到动态类型的脚本语言的非性能至关重要的实现,以表示脚本世界中的变量,但是即使是扩展(Boost.Spirit/example/qi/compiler_tutorial,解析器和运行时也不需要这样做) )。

对于从解析器(例如Boost.Spirit.X3)到库API(例如ASIO)的其他所有事物,通常都会有一种更快/更好/更具体的选择,因为很少有东西真正是“任何东西” ,大多数都比这更具体。

  • std::variant和/或std::optional表示“几乎所有值”
  • std::packaged_task / std::function +用于“带参数回调”的lambda,在C API中就是void*的情况。

特别是,我不会盲目地插入它来代替void*,因为它may allocate在堆上的内存对于高性能代码可能是致命的。

答案 2 :(得分:1)

在Wt中使用它来为tabular data提供一个非模板接口。

对于内置和Wt类型,有一些到字符串的转换,您可以通过专门设置Wt::any_traits来注册其他转换。这样一来,任何内容都可以显示为表中的条目,而视图类不必了解它们所显示的类型。

答案 3 :(得分:1)

std::any词汇类型。当您需要存储任何东西时,可以使用它作为值。

有许多“第一级”用途:

  1. 与本身具有这种类型的脚本语言进行交互时,这很自然。

  2. 当属性树具有高度多态的内容,并且树的结构与树的生产者和使用者分离时。

  3. 当替换通过中间层传递的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::function的很小的实现。基本上,我已经使用any来键入“擦除复制/移动/销毁”。

您可以在其他地方使用它来解决类似的问题(在进行某些类型的擦除操作并且还想键入“擦除复制/移动/销毁”的情况下)或generalize it