BiG*_*YaN 31 c c++ syntax metaprogramming syntactic-sugar
我一直在研究Ruby并发现它的关键字"直到"和"除非"非常有趣.所以我认为在C/C++中添加类似关键字的好方法是什么.这就是我想出的:
#define until(x) while(!(x))
#define unless(x) if(!(x))
Run Code Online (Sandbox Code Playgroud)
我正在寻找一些建议.谁能提出更好的选择?
这是我编写的一个程序示例,用于说明我打算做什么:
#include <stdio.h>
#include <stdlib.h>
#define until(x) while(!(x))
#define unless(x) if(!(x))
unsigned int factorial(unsigned int n) {
unsigned int fact=1, i;
until ( n==0 )
fact *= n--;
return fact;
}
int main(int argc, char*argv[]) {
unless (argc==2)
puts("Usage: fact <num>");
else {
int n = atoi(argv[1]);
if (n<0)
puts("please give +ve number");
else
printf("factorial(%u) = %u\n",n,factorial(n));
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你能指出一些可以在C或C++中使用的类似技巧的参考文献,那将是很棒的.
Jam*_*lis 108
谁能提出更好的选择?
是.根本不要这样做.只需直接使用while
和if
语句.
当您使用C或C++编程时,请使用C或C++编程.虽然until
并且unless
可能在某些语言中经常使用和惯用,但它们不是C或C++.
Jac*_* V. 16
你做的方式在我看来是正确的方法,如果你要去做的话.因为宏的扩展与你期望的那样相似[1],我认为使宏看起来像syntax()是有效的,而不是通常推荐的SCARY_UPPERCASE_MACROS()用来表明这段代码没有不遵循通常的语法,你应该只仔细使用它.
[1]唯一的缺陷是无法声明变量,无论如何都不太可能,并且如果使用不当可能会在正确的位置产生错误,而不是做一些奇怪的事情.
此外,即使可读性的小幅增加也很重要,因此能够说until (
而不是while (!
真的能够更容易地阅读许多循环.如果结束条件更容易被认为是一种异常条件(无论是否存在),那么以循环方式编写循环会使其更容易阅读.所以即使它只是语法糖,我认为有理由考虑它.
但是我不认为这是值得的.好处很小,因为大多数程序员习惯于阅读if (!
并且成本是真实的:阅读代码的任何人都必须检查这是一个宏,还是自定义编译器,以及它是否符合他们的想法.它可能误导你认为你可以做的事情i=5 unless xxxx;
.这种微小的改进,如果广泛使用,会破坏语言,因此通常最好以标准方式做事,并慢慢采取改进措施.
但是,它可以做得很好:整个boost和tr1,特别是使用模板看起来像库的扩展的东西,涉及以各种方式扩展C++,其中许多不被采用,因为它们似乎不值得它,但其中很多都有小的或非常广泛的吸收,因为它们做了真正的改进.
BЈо*_*вић 13
这让我想起了我在某人的代码中看到过的东西:
#define R return;
Run Code Online (Sandbox Code Playgroud)
此外,使代码难以理解,会增加维护成本.
我建议最好不要使用它们.
你不能在Ruby风格中使用它们
`printf("hello,world") unless(a>0);`
Run Code Online (Sandbox Code Playgroud)
是非法的.
而且C程序员更难理解代码.同时额外的宏可能是一个问题.
如果您要定义宏,那么让它们看起来非常丑陋是一种很好的做法.特别是,它们应该是全部大写,并且具有某种前缀.这是因为没有命名空间,也没有与类型系统或C++重载解析的协调.
因此,如果您的宏被调用,BIGYAN_UNNECESSARY_MACRO_UNTIL
那么它将不会"超越苍白".
如果你想用新的循环结构扩展C++,可以考虑在C++ 0x中调查lambdas,你可以允许:
until([&] { return finished; }, [&]
{
// do stuff
});
Run Code Online (Sandbox Code Playgroud)
它并不完美,但它比宏更好.
如果它们仅在您自己的代码库中使用,我认为您的宏不是特别糟糕.
这篇文章
可能对你有意思.话虽这么说,当我们在C++中使用它们时,我会看到你的宏的一些缺点.
例如,我们不能写为:
until (T* p = f(x)) ...
unless (T* p = f(x)) ...
Run Code Online (Sandbox Code Playgroud)
另一方面,我们可以写为:
while (T* p = f(x)) ...
if (T* p = f(x)) ...
Run Code Online (Sandbox Code Playgroud)
至于unless
,如果我们将其定义为:
#define unless(x) if (x) {} else
Run Code Online (Sandbox Code Playgroud)
那我们就可以写了unless (T* p = f(x)) ...
.但是,在这种情况下我们不能else
在它之后添加子句.