定制化C++是否可行?

8

对于我的项目,我通常为诸如unsigned int、char和double以及std::string等类型定义许多别名。

我还将and别名为&&,or别名为||,not别名为!等等。

  • 这种做法是否被认为是不好的实践还是可以接受的?

5
如果你希望其他加入你项目的开发者能够有生产力,那么答案是否定的。 - cdhowie
4
你是否将begin别名为{,将endfin别名为},并将ever别名为(;;)(true)了? - FrustratedWithFormsDesigner
6
“and”、“or”、“not”等都是C++的一部分。 - CB Bailey
7
概括回答:毫无头绪地滥用预处理器,特别是为了“方便”而进行一对一的语法更改,是致命的罪过。 - user395760
4
C++已经支持andor这两个"替代标记",因此您无需自己实现。 虽然要在MSVC++中支持它们,您可能需要使用/Za选项(这通常会带来很多问题),或包含 iso646.h头文件。 但是,大多数评论认为,对于大多数程序员来说,使用符号运算符更易读且更可取。 - Michael Burr
显示剩余13条评论
6个回答

22

定义类型以在代码中添加上下文是可以接受甚至是鼓励的。 瞎折腾运算符只会鼓励下一个需要维护你的代码的人带枪到你家。


10
这让我想起以下名言:“编写代码时,要像维护代码的人是一个精神病连环杀手,而且他知道你住在哪里” :) - SebastianK
1
谷歌搜索+谷歌地图+街景视图。甚至一个机器人也可以像这样跟随路径。 - Tim Williscroft
@Tim Williscroft:听起来像是一部动作电影情节:机器人可能被派遣来自未来,消灭那些对有感知的计算机构成威胁的人——哦,糟糕! - Piskvor left the building

11

考虑一下那些习惯于使用C++的新手,他们在维护你的项目时可能会遇到困难。

请注意,有许多更有效的别名可能性。一个很好的例子是复杂的嵌套STL容器。

例子:

typedef int ClientID;
typedef double Price;
typedef map<ClientID, map<Date, Price> > ClientPurchases;

现在,不再使用

map<int, map<Date, double> >::iterator it = clientPurchases.find(clientId);

你可以写

ClientPurchases::iterator it = clientPurchases.find(clientId);

这似乎更清晰易读。


10
如果你只是在 毫无意义地 重命名语言特性(与@Vlad给出的示例相反),那么这就是错误的做法
它肯定会使代码变得不太可读 - 熟练掌握C ++的任何人都会看到(x ? y : z)并知道这是一个三元条件运算符。虽然ORLY x YARLY y NOWAI z KTHX 可能是同样的东西,但它会让查看者困惑:“这个YARLY NOWAI是否完全相同于? :,为了作者方便而重命名,还是有微妙的差别?”如果这些“别名”与标准语言元素相同,则它们只会减慢下一个维护您的代码的人的速度。
TLDR:阅读代码,任何代码,已经很难了,不要总是去查找您自己的私有备用语法。

1
真正熟练的人会知道 and 已经是一个关键字 :D - CiscoIPPhone
2
@Ciscol:吹毛求疵:它实际上是一个预处理标记(解析为&&),而不是关键字。;-) - Konrad Rudolph
@CiscoIPPhone:没错。已更改为一个更傻的例子,我真心希望那些不是真正的关键词;) - Piskvor left the building

5
那太可怕了。请不要那样做。写惯用的C++,而不是一些充斥着宏的怪物。通常情况下,在除了非常特定的情况(例如BOOST_FOREACH宏)之外,定义这样的宏实践极其糟糕。
话虽如此,“and”、“or”和“not”实际上已经是C++中“&&”、“||”和“!”的有效别名!只是Visual Studio只有在您首先包含标准头文件时才知道它们。其他编译器不需要这个。
类型是另一回事。根据上下文使用typedef创建类型别名,如果它增加了代码的表现力,则是有意义的。然后鼓励这样做。但是,更好的方法是创建自己的类型而不是别名。例如,我无法想象为什么要为std :: string创建别名-为什么不直接使用std :: string?(当然,例外是通用数据结构和算法。)

4
  • "and"、 "or"、"not" 是可以使用的,因为它们是语言的一部分,但是最好按照其他 C++ 程序员的写法来编写 C++ 代码,很少有人会使用它们。不要给它们进行别名定义:它们是保留名称,在预处理器中使用保留名称通常是无效的。如果您的编译器在其默认模式下没有提供它们(即不符合标准),您可以使用 #define 来虚拟它们,但是如果您更改编译器或更改编译器选项,未来可能会遇到麻烦。

  • 对于内置类型而言,使用 typedefs 在某些情况下可能是有意义的。例如,在 C99 (但不适用于 C++03) 中,存在扩展整数类型,如 int32_t,它指定了一个 32 位整数,在特定系统上可能是 int 的一个 typedef。它们来自于 stdint.h (<cstdint> 在 C++0x 中),如果你的 C++ 编译器不提供它作为扩展,你可以通常找到或编写一个可以在你的系统上工作的版本。如果您有某些目的,未来可能需要使用不同的整数类型 (也许是在不同的系统上),那么请使用描述您选择该类型用于此目的的重要属性的名称来隐藏 "真实" 类型。如果你只是认为 "int" 太短了,应该改成 "integer",那么你并没有真正帮助任何人,甚至连你自己也没有帮助,因为这样做只是一种徒劳的尝试去修改 C++ 语言中表面的东西。它只是增加了额外的间接性而没有什么好处,在长远来看,更好的做法是学习 C++,而不是试图去修改 C++ 以使其变得更有“意义”。

  • 除非在类似扩展整数类型的情况下,我想不出使用任何其他名称来替代 string 的好理由,其中您的名称可能会是某些构建的 string 的 typedef,而在另一些构建中则是 wstring

  • 如果您不是以英语为母语的人,并且正在尝试将 C++ “翻译”成其他语言,那么我可以理解您的观点,但我认为这不是个好主意。即使是您所选择的翻译,其他说您的语言的人也会比您更熟悉 C++。但我是以英语为母语的人,所以我真的不知道这是否有多大的差异。考虑到全世界有多少 C++ 程序员并没有翻译语言,我怀疑这与所有文档都是用英语编写相比,不是一个很大的问题...


1
Excel和Visual Basic尝试翻译关键字一段时间,结果非常糟糕(是的,甚至比VB和Excel本来就糟糕的情况还要糟糕)。 - Fabio Fracassi

0
如果每个C++开发人员都熟悉你的别名,那还好,但是你通过这些别名引入了一种新语言给需要维护你代码的人。
为什么要添加这额外的思维步骤,大部分情况下并没有增加任何明确性(对于任何C/C++程序员来说,&&和||的功能非常明显,无论如何在C++中你都可以使用and和or关键字)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接