定制 C++预处理器/类型宏
看到了 Ruby 和 Python 中元编程的优势,但在实际工作中必须使用 C++ 和 C 等较低级语言,我正在考虑如何将两者结合起来。一个例子是对任意结构/类的列表进行排序的简单问题。例如:
struct s{
int a;
int b;
};
vector<s> vec;
for(int x=0;x<10;x++){
s inst;
inst.a = x;
inst.b = x+10;
vec.push_back(inst);
}
最终,我希望能够使用最少量的样板代码对 inst 进行任意排序。我能想到的最简单的方法是利用 STL 的排序:
sort(vec.begin(),vec.end());
但这需要我编写一个可以比较“struct s”的方法。我宁愿做的是:
sort(vec,a ASC,b DESC);
这显然不是有效的 C++。
实现我的梦想的最佳方式是什么?如果我有某种类型的宏,它会向我揭示向量元素的类型,那么编写 C 预处理器宏来创建排序所需的函数就很简单了。
另一种选择似乎是编写我自己的预处理器。这很有效,直到我必须再次推断出“vec”的类型。有没有简单的方法可以做到这一点?
背景:更少的代码=更少的错误、编程竞赛。
Having seen the advantages of metaprogramming in Ruby and Python, but being bound to lower-level languages like C++ and C for actual work, I'm thinking of manners by which to combine the two. One instance comes in the simple problem for sorting lists of arbitrary structures/classes. For instance:
struct s{
int a;
int b;
};
vector<s> vec;
for(int x=0;x<10;x++){
s inst;
inst.a = x;
inst.b = x+10;
vec.push_back(inst);
}
Ultimately, I'd like to be able to sort inst arbitrarily with a minimal amount of boilerplate code. The easiest way I can see to do this is to make use of STL's sort:
sort(vec.begin(),vec.end());
Yet this requires me to write a method that can compare "struct s"s. What I'd rather do is:
sort(vec,a ASC,b DESC);
Which is very clearly not valid C++.
What is the best way to accomplish my dream? If I had some sort of typeful macro, that would reveal to me what the type of a vector's elements were, then it would be trivial to write C preprocessor macros to create the function required to do the sorting.
The alternative seems to be to write my own preprocessor. This works well, up until the point where I have to deduce the type of "vec" again. Is there an easy way to do this?
Context: Less code = less bugs, programming competitions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于上述内容,您可以使用 Boost.Lambda内联编写比较函数,就像 Python lambda 一样:
这当然假设您按 a 排序。
如果您要查找的表达式要复杂得多,那么最好编写一个单独的函数;即使在像 Python 和 Ruby 这样原生支持闭包的语言中,复杂的闭包也变得非常难以阅读。
警告:上面的代码未经测试。
希望这有帮助!
For the above, you can use Boost.Lambda to write your comparison function inline, just like a Python lambda:
This of course assumes that you are sorting by a.
If the expressions you are looking for are far more complex, you are better off writing a separate function; even in languages like Python and Ruby with native support for closures, complex closures become quite unreadable anyway.
Warning: The code above is untested.
Hope this helps!
我会坚持为
struct
编写一个比较运算符。定义比较运算符的好处是,您不会最终得到分散在各处的多个 lambda 比较。您可能多次需要比较运算符,那么为什么不在逻辑位置(与类型一起)定义一次呢?就我个人而言,我更喜欢编写一次代码并将其保存在特别容易找到的地方。我也喜欢编写与我所使用的语言相关的惯用代码。在 C++ 中,我期望使用构造函数、析构函数、小于运算符等。您最好编写一个小于运算符,然后让 std::sort(vec.begin(), vec.end()) 完成其正确的工作。如果您确实想让代码清晰,那么可以这样做:
如果您定义一个成员函数来进行比较,然后在命名空间级别提供运算符,那么当您必须否定比较时,生活会容易得多。例如:
这段代码未经测试,但您已经明白了。
I would stick with writing a comparison operator for the
struct
. The bonus of having a comparison operator defined is that you don't end up with multiple lambda comparisons scattered all over the place. Chances are that you will need a comparison operator more than just once, so why not define it once in the logical place (along with the type)?Personally, I prefer writing code once and keeping it some place that is particularly easy to find. I also favor writing code that is idiomatic with respect to the language that I am writing in. In C++, I expect constructors, destructors, less-than operators, and the like. You are better off writing a less-than operator and then letting
std::sort(vec.begin(), vec.end())
do its proper job. If you really want to make your code clear, then do something like:If you define a member function to do the comparison and then provide the operator at the namespace-level, life is much easier when you have to negate the comparison. For example:
This code is untested but you get the idea.
如果您使用的是 C++11,则可以使用 Linq 对其进行排序:
或者如果您不喜欢查询语法,您也可以使用扩展方法:
两者在功能上是等效的。
If you are using C++11, you can use Linq to sort it like this:
Or if you don't like the query syntax, you can use the extension methods as well:
Both are functionally equivalent.
对于 C++,标准库提供 algorithms 标头,其中包含许多适用于各种容器的有用函数。适合您的目的的一个例子是:
sort 有一个看起来像这样的原型:
大多数这些算法应该适用于任何标准容器(一些特定于排序容器,一些关联容器等)。我相信排序(和其他)甚至可以与数组一起使用(迭代器是算法的基础,旨在尽可能模拟指向数组元素的指针。)
简而言之,使用现代 C++,您将不需要特殊的预处理器来实现你正在尝试做的事。
顺便说一句,如果您声明您正在使用 std 或 std::sort,则
sort(vec.begin(),vec.end())
有效c++;For c++ the standard library offers the algorithms header which contains many useful functions that work on various containers. An example for your purposes would be:
sort has a prototype that looks something like:
Most of these algorithms should work for any of the standard containers (some are specific to sorted containers, some associative, etc). I believe sort (and others) will even work with arrays (Iterators, the foundation of algorithms, are built to emulate pointers to array elements as closely as possible.)
In short, using modern c++ you will not need a special preprocessor to achieve what you're trying to do.
BTW, if you've declared that you're using std or std::sort, then
sort(vec.begin(),vec.end())
is valid c++;