【问题标题】:Python-style variables in C++C++ 中的 Python 样式变量
【发布时间】:2016-10-05 16:52:14
【问题描述】:

我正在开发一个 C++ 项目,并试图弄清楚如何制作一个“动态”变量。

在 Python 中,变量可以有多种类型:

variable = 0
variable = "Hello"

在 Java 中,这也是(在某种程度上)可以实现的:

Object o = 0;
o = "Hello";

从我能找到的与 C++ 相关的内容来看,那里没有 object 类型或“动态”对象。

我需要这个的原因是我正在尝试创建一个接受以下任何类型的对象: intfloatcharstringbool,并允许我进行如下操作:

object o = 0; // currently an int
o -= 2.5; // now a float
o += "Test"; // now a string

这种变量是否有任何默认功能?如果没有,可以用宏、struct's 等来完成吗?

我发现了这样的事情:

template <typename name>

但是不知道怎么用。

【问题讨论】:

  • C++17 将有 std::any 这正是你想要的。现在,您可以使用boost::any 或推出您自己的实现。然而,这并不是动态的,确切地说。
  • @user2296177 我正在使用 C++11 并希望(但如果不可能,我很乐意放弃支持)具有向后兼容性。我对C++没用,你能给我举个例子吗?我不知道从哪里开始......
  • 您始终可以创建一个类,该类将包含您想要支持的所有类型的向量,然后为其添加一个接口。但从表面上看,这在可维护性和可读性方面似乎是一个非常糟糕的主意。我会考虑非常努力地实施这样的事情,并尝试提出一个完全不同的解决方案。
  • @mirosval 我一直在考虑这样做,但后来我可能需要为无限数量的对象类型扩展它。
  • 为什么首先需要为变量分配不同的类型?

标签: python c++ types type-safety strong-typing


【解决方案1】:

您可以使用boost.variant 库。基本使用说明here。简而言之,就像

using var_t = boost::variant<bool,int,double,string, boost::blank_t>;
var_t var = "hello";
std::cout << boost::get<std::string>(var) << '\n';
std::cout << var << '\n'; // if all possible stored types are streamable

有些不直截了当的部分是在不知道确切类型的情况下访问值。这需要static visitor

如果您想知道 anyvariant 之间有什么区别 - 您并不孤单,here is the comparison chart

【讨论】:

  • 您能详细说明一下吗?我不知道如何实现这些来自全 Java/Python 背景的东西。
  • 我什么都不知道,但如果您不熟悉 c++,这可能会有所帮助:boost.org/doc/libs/1_61_0/doc/html/variant.html。您在模板中找到的不是您要寻找的。​​span>
  • @frayment - 您不太可能遇到任何平台相关行为或库问题,例如variant
  • boost::variant 没有get 方法,你的意思是boost::get
  • @frayment - 大多数boost 库(variant 包括)是“仅标题”,这意味着一旦编译您的二进制/库将只有它正在使用的内容,而您将没有任何额外的运行时依赖项。但是你确实需要硬盘上的 boost/include 目录,这就是你付出的代价:)
【解决方案2】:

每种语言都有自己的惯用结构,您应该尝试在 C++ 中模仿 Python 代码。正如@user2296177 所说,最接近的 C++ 工具(在当前版本中)是 boost::any,它也作为 std::any 包含在 C++17 中。

但即使 boost:any 也有一些限制:分配给 boost::any 的类型必须是可复制构造的,并且它们的析构函数不能抛出异常。

如果您只需要接受已知的类型列表,则可以使用旧的(来自 C 的)联合或它们的 boost 自动等效 boost::variant。

但实际上,您应该想知道为什么需要它,您打算如何跟踪实际类型,是否需要允许转换或别名。因为除了动态 Python 变量之外,C++ 还允许在类型之间进行转换或别名。

TL/DR:不要试图模仿 Python 习语,并仔细分析您的真正需求。在某些用例中,联合可能是工具,在其他一些用例中可能需要 void 指针或专用结构。这真的取决于实际用例。

【讨论】:

  • 我遇到的问题是,我可能接受任何类型的对象。我将程序设计为根本不跟踪类型,而是直接对变量应用操作并根据请求打印结果。
  • @Serge - AST 解析是 C++ 中 variant/any 的有效用例,有时也解析标记类型值协议。不管是什么语言,恕我直言,无论导致更便宜/可读/快速(无论优先级如何)的代码都是一个很好的解决方案。
  • @frayment:您要处理的所有类型都有哪些通用操作?你想只处理自定义类型(可以从一个单一接口派生)还是标准类型(字符串、列表、映射)甚至内在函数(int、float、char)?允许的类型列表是否受到限制?
  • @SergeBallesta 运营:+-*/% += -= *= /= %= == = &amp;= |= ^= ~= &lt;&lt;= &gt;&gt;= &lt;&lt; &gt;&gt; &amp;|^~。而且我需要自定义类型 原语。在这个阶段,名单有些开放。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多