定义一个像Python“with”语句一样工作的C宏有什么缺点?

时间:2011-12-17 03:21:19

标签: python c++ control-structure

在使用C预处理器玩了一下后,我想到了一种类似于具有控制结构的Python的方法,定义如下:

#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执行一次。

这有什么缺点吗?如果我足够混淆迭代变量,几乎没有机会发生名称冲突,它只使用标准的预处理器功能,似乎没有任何反击的可能性,而且很容易理解。

这似乎太好了,不是真的 - 有没有理由不在任何地方使用?

5 个答案:

答案 0 :(得分:6)

  

有没有什么理由不在任何地方使用?

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

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

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

C ++具有非常重要的值类型概念和基于范围的堆栈变量的确定性破坏。这导致非常重要的习惯用语,如SBRM(范围限制资源管理,也称为RAII)。

答案 1 :(得分: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程序员的情况下难以阅读的代码。

如果我读了一个使用你的with()宏的C ++程序,我真的无法理解它在做什么没有(a)意识到with()是一个宏(宏通常给出全部大写名称),(b)追踪宏定义,以及(c)破译扩展宏导致的相当奇怪的C代码。这是假设我没有陷入认为它是特定于编译器的扩展,或者C具有我不知道的with语句的陷阱。

或者,如果我碰巧理解Python with语句,那么我仍然需要(a)意识到你的with()宏旨在模仿Python with语句,并且( b)相信你做对了。

多年前,我想到了这个:

#define ever ;;
...

for (ever) { ... }

非常聪明。我仍然觉得它很聪明;但我不再认为聪明才是一件好事。

答案 2 :(得分:1)

  

这似乎太好了,不是真的 - 有什么理由不这样做   到处使用?

当然,这是一个很适合你的伟大结构,但团队中其他人呢?未来你 - 在六个月内 - 不记得你写的那个可爱的宏了怎么样?

简而言之,像这样的句法体操在家里是很好的练习,但在协作环境中甚至是你将来会保留的代码都很糟糕。坚持最佳实践,您的代码将更容易维护和理解。

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

答案 3 :(得分:1)

这真的&#34;与&#34;? &#34;&#34;的最大优势在Python中,它适用于上下文管理器,它负责在&#34;中使用&#34;自动关闭/释放/解锁/取消分配变量。声明。在C ++中,有一些标准的方法可以做到这一点。例如,auto_ptr将负责自动删除使用new分配的指针。在重新发明之前先学习这些标准习语。

答案 4 :(得分:0)

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