如何清楚地指定我正在传递哪些参数以及哪些保持默认?
因此询问: C++ 中的默认参数
假设我有一个函数如下: void f(int p1=1, int p2=2, int p3=3, int p4=4);
我想仅使用一些参数来调用它 -休息会设为默认值。
像这样的东西是可行的:
template<bool P1=true, bool P2=true, bool P3=true, bool P4=true>
void f(int p1=1, int p2=2, int p3=3, int p4=4);
// specialize:
template<>
void f<false, true, false, false>(int p1) {
f(1, p1);
}
template<>
void f<false, true, true, false>(int p1, int p2) {
f(1, p1, p2);
}
// ... and so on.
// Would need a specialization for each combination of arguments
// which is very tedious and error-prone
// Use:
f<false, true, false, false>(5); // passes 5 as p2 argument
但它需要太多代码才能实用。
有更好的方法吗?
Asked because of this: Default argument in c++
Say I have a function such as this: void f(int p1=1, int p2=2, int p3=3, int p4=4);
And I want to call it using only some of the arguments - the rest will be the defaults.
Something like this would work:
template<bool P1=true, bool P2=true, bool P3=true, bool P4=true>
void f(int p1=1, int p2=2, int p3=3, int p4=4);
// specialize:
template<>
void f<false, true, false, false>(int p1) {
f(1, p1);
}
template<>
void f<false, true, true, false>(int p1, int p2) {
f(1, p1, p2);
}
// ... and so on.
// Would need a specialization for each combination of arguments
// which is very tedious and error-prone
// Use:
f<false, true, false, false>(5); // passes 5 as p2 argument
But it requires too much code to be practical.
Is there a better way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用命名参数习惯用法(→ 常见问题解答链接)。
Boost.Parameters 库(→ link)也可以解决此任务,但代价是代码冗长且清晰度大大降低。它在处理构造函数方面也存在缺陷。当然,它需要安装 Boost 库。
Use the Named Parameters Idiom (→ FAQ link).
The Boost.Parameters library (→ link) can also solve this task, but paid for by code verbosity and greatly reduced clarity. It's also deficient in handling constructors. And it requires having the Boost library installed, of course.
看看 Boost.Parameter 图书馆。
它在 C++ 中实现命名参数。例子:
Have a look at the Boost.Parameter library.
It implements named paramaters in C++. Example:
尽管 Boost.Parameters 很有趣,但(不幸的是)它遇到了许多问题,其中占位符冲突(并且必须调试奇怪的预处理器/模板错误):
将创建您随后使用的
_p1
占位符稍后。如果您有两个不同的标头声明相同的占位符,则会发生冲突。不好玩。有一个更简单(概念上和实践上)的答案,基于
Builder
模式,有点是命名参数习惯用法。不是指定这样的函数:
您指定一个结构,您将在该结构上覆盖
operator()
:通常,它与Chaining相结合,后者使setter返回对当前值的引用对象以便可以链接调用在一条线上。
调用是:
我看到一个变体将强制参数作为参数传递给operator(),这避免了将参数保留为属性,但语法有点奇怪:
一旦编译器内联了所有构造函数和 setter 调用(这就是为什么它们在这里定义,而
operator()
不是),与“常规”函数调用相比,它应该会产生类似的高效代码。Although Boost.Parameters is amusing, it suffers (unfortunately) for a number of issues, among which placeholder collision (and having to debug quirky preprocessors/template errors):
Will create the
_p1
placeholder that you then use later on. If you have two different headers declaring the same placeholder, you get a conflict. Not fun.There is a much simpler (both conceptually and practically) answer, based on the
Builder
Pattern somewhat is the Named Parameters Idiom.Instead of specifying such a function:
You specify a structure, on which you will override the
operator()
:Generally, it is combined with Chaining which consists in making the setters return a reference to the current object so that the calls can be chained on a single line.
The invocation is:
I've seen a variant putting the mandatory arguments as parameters to
operator()
, this avoids keeping the arguments as attributes but the syntax is a bit weirder:Once the compiler has inlined all the constructor and setters call (which is why they are defined here, while
operator()
is not), it should result in similarly efficient code compared to the "regular" function invocation.这并不是真正的答案,但是......
在C++模板元编程 David Abrahams 和 Aleksey Gurtovoy(2004 年出版!)作者对此进行了讨论:
他们接着说:
这是在模板元编程和 Boost::MPL 的背景下。我不太确定他们的“直接”实现如何与默认参数配合,但我认为它是透明的。
This isn't really an answer, but...
In C++ Template Metaprogramming by David Abrahams and Aleksey Gurtovoy (published in 2004!) the authors talk about this:
They go on to say:
This was in the context of template metaprogramming and Boost::MPL. I'm not too sure how their "straighforward" implementation would jive with default parameters, but I assume it would be transparent.