0

在玩了一点 C 预处理器之后,我想到了一种方法来拥有类似于具有控制结构的 Pythonian 的东西,定义如下:

#define with(var) for(int i##__LINE__=0;i##__LINE__<1;)for(var;i##__LINE__<1;++i##__LINE__)

示例用法:

#include <cstdio>
#include "FileClass.hpp"
#include "with.hpp"

int main(){
    with(FileClass file("test.txt")){
        printf("%s\n",file.readlines().c_str());}
    return 0;}

这个想法是双重嵌套的 for 循环有一个外部混淆迭代变量,该变量在内部循环中递增一次以中断它。这会导致以下代码在其范围内执行一次 var。

这有什么缺点吗?如果我对迭代变量进行了足够的混淆,则几乎不会有名称冲突的可能性,它仅使用标准预处理器功能,似乎没有任何事与愿违的可能性,而且很容易理解。

这似乎好得令人难以置信——有什么理由不到处使用吗?

4

5 回答 5

6

有什么理由不到处使用吗?

是的,C++ 不是 Python,如果我正确理解了您的代码,这完全一样:

{
  FileClass file("test.txt");
  printf("%s\n", file.readlines().c_str());
}

那么,有什么缺点呢?不自然的语法,使用预处理器进行代码混淆,使用更多样板代码实现与上述相同的事情,以及 C++ 的单一使用。足够的?

C++ 有一个非常重要的概念,即值类型和基于范围的堆栈变量的确定性销毁。这导致了非常重要的习惯用法,例如 SBRM(范围绑定资源管理,也称为 RAII)。

于 2011-12-17T03:33:31.640 回答
4

它在本质上类似于原始 Bourne shell 中使用的宏,后者是用 C 编写的。它们旨在提供类似于 Algol 68 的语法,这显然是 Bourne 的首选语言。

来自http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h的小样本:

#define IF    if(
#define THEN  ){
#define ELSE  } else {
#define ELIF  } else if ( 
#define FI    ;}

结果往往是 C 程序员(他们必须熟悉您的宏以及 C 本身的语法)或 Algol 68 或您的情况下的 Python 程序员难以阅读的代码。

如果我阅读了一个使用您的宏的 C++ 程序,如果没有(a)意识到这是一个宏(宏通常被赋予全大写名称),(b)跟踪宏定义,with()我将无法真正理解它在做什么with()(c) 破译因扩展宏而产生的相当奇怪的 C 代码。这是假设我没有落入认为它是特定于编译器的扩展的陷阱,或者 C 有一个with我不知道的语句。

或者,如果我碰巧理解 Pythonwith语句,那么我仍然需要 (a) 意识到您with()的宏旨在模仿 Pythonwith语句,并且 (b) 相信您能正确理解它。

多年前,我认为这是:

#define ever ;;
...

for (ever) { ... }

很聪明。我仍然认为它很聪明。但我不再认为聪明是一件好事。

于 2011-12-17T03:44:30.537 回答
1

这似乎好得令人难以置信——有什么理由不到处使用吗?

当然,这对你来说是一个很好的结构,但是团队中的其他人呢?未来的你——在六个月内——不记得你写的那个可爱的宏怎么办?

简而言之,像这样的句法体操在家中是很好的练习,但在协作环境中却很糟糕,甚至对于您将来独自维护的代码也是如此。坚持最佳实践,您的代码将更容易维护和理解。

这并不是说你不应该在家里做这种事情。做你喜欢的事,让你的大脑保持灵活。但是不要在生产中使用你的热身练习!

于 2011-12-17T03:38:00.793 回答
1

这真的是“与”吗?Python 中“with”的最大优势在于它与上下文管理器一起使用,后者负责自动关闭/释放/解锁/取消分配“with”语句中的变量。在 C++ 中,有执行此操作的标准方法。例如,auto_ptr将处理使用 new 分配的自动删除指针。在自己重新发明它们之前学习这些标准习语。

于 2011-12-17T03:45:03.297 回答
0

这样做的明显缺点是没有人能够阅读你的意大利面条混蛋-Python-in-C++ 代码。祝你好运维护该代码。

于 2011-12-17T03:34:58.163 回答