将 n 个二进制调用转换为 C++ 中的一个 n 元调用?
我们的代码库中有一个辅助函数来连接两个(Windows)路径字符串:
CString AppendPath(CString const& part1, CString const& part2);
它经常以这种方式使用:
const CString filePath = AppendPath(AppendPath(AppendPath(base, toplevel), sub1), filename);
这是相当可以接受的,但它让我想知道 C++(或 C++0x)中是否有可能使用(模板?)函数将二进制函数调用链接在一起。
也就是说,给定一个函数 T f(T arg1, T arg2) 是否可以编写函数 T ncall(FnT fn, T arg1, T arg2, T arg3, ...) 会像上面的示例一样调用 f
并返回结果?
// could roughly look like this with my example:
const CString filePath = ncall(&AppendPath, base, toplevel, sub1, filename);
拜托,这个问题是关于转换的,不是< /strong> 关于处理或连接路径字符串的最佳方法!
编辑: 感谢 deft_code 的 回答为我所要求的内容提供正确的术语:折叠(高阶函数)。 (请注意,我已决定接受 Matthieu 的答案,因为他的解决方案不需要 C++0x。)
We have a helper function in our codebase to concatenate two (Windows) path strings:
CString AppendPath(CString const& part1, CString const& part2);
It is often used in this way:
const CString filePath = AppendPath(AppendPath(AppendPath(base, toplevel), sub1), filename);
This is rather acceptable, but it got me wondering if there is some possibility in C++ (or C++0x) to use a (template?) function to chain binary function calls together.
That is, given a function T f(T arg1, T arg2)
is it possible to write a function T ncall(FnT fn, T arg1, T arg2, T arg3, ...)
that will call f
like in my example above and return the result?
// could roughly look like this with my example:
const CString filePath = ncall(&AppendPath, base, toplevel, sub1, filename);
Please, this question is about the transformation and not about the best way to handle or concatenate path strings!
Edit: Thanks to deft_code's answer for providing the correct term for what I was asking for: Fold (higher-order function). (Note that I have settled on accepting the answer of Matthieu because his solution does not require C++0x.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果没有 C++0x,也可以使用链接(我不建议重载逗号运算符,语法会变得很奇怪)。
语法有些不同,但非常接近:
只需创建一个临时对象即可完成,该对象将通过
operator()
的重载执行串联,并且可通过operator CString 隐式转换() 常量
。然后,您调整
AppendPath
以返回这样的对象:(注意,实际上您可以直接将其命名为
AppendPath
)按照 @Martin 的建议使其通用:
在 ideone。
Without C++0x, it's also possible to use chaining (I don't recommend overloading the comma operator, the syntax gets weird).
The syntax is somewhat different, but very close:
This is done simply by creating a temporary object that will perform the catenation through an overload of
operator()
and which will be implicitly convertible throughoperator CString() const
.Then, you tweak
AppendPath
to return such an object:(Note, actually you could directly name it
AppendPath
)Making it generic as per @Martin's suggestion:
Code validated on ideone.
在 C++0x 中,您可以使用可变参数模板。也许是这样的:
In C++0x, you can use variadic templates. Something like this, perhaps:
制作Martinho Fernandes的解决方案< /a> 更通用:
使用:
但是,AppendPath 可以简单地以这种风格编写:
当然,您可以添加此重载并在代码中透明地使用它。
或者传递一个initializer_list:
代码:
注意最后一个AppendPath 适用于任何类似STL 的容器。您还可以将这些重载添加到代码中并透明地使用它们。
Making Martinho Fernandes' solution more generic:
Use:
However, AppendPath could simply be written in this style:
You can, of course, add this overload and use it transparently in your code.
Or pass an initializer_list:
Code:
Notice the last AppendPath works with any STL-like container. You can also add these overloads to your code and use them transparently.
在调用 AppendPath 的这种特定情况下,我只需编写函数的重载,该函数的实现就是您的第二行代码。
在一般情况下,我会编写一系列模板:
我确信可以轻松自动生成这些模板。
In this specific case of calling
AppendPath
I'd just write an overload of the function which has as its implementation your second line of code.In the general case I'd write a series of templates:
Which I'm sure could be easily generated automatically.
每个人都非常接近通用的foldl 实现。这是一个比所提出的问题更通用的解决方案。它接受诸如
T f(T arg1, T arg2)
以及T1 f(T2 arg1, T3 arg2)
之类的函数。此外,我将函数命名为 foldl 以向其函数根源致敬。这是如何解决您的问题的示例:
另一个展示foldl所有优势的示例:
请参阅 ideone< 的实际输出/代码/a>.
Everyone is soo close to a general foldl implementation. Here is an even more general solution than the question asked. It accepts functions like
T f(T arg1, T arg2)
as well asT1 f(T2 arg1, T3 arg2)
. Also I named the function foldl in homage to its functional roots.An example of how this would solve your problem:
Another example showing off all of foldl's strength:
See the output / code in action at ideone.