[英]Function overloading inside overloaded function
I am using C++14
(and pretty new to it). 我正在使用
C++14
(而且还很新)。 I have 3 overloaded functions func
within which another overloaded function do_something
gets called depending on its parent function ( func
). 我有3个重载函数
func
,其中另一个重载函数do_something
取决于其父函数( func
)被调用。
int func(int a) {
bar(a);
foo();
}
int func(int a, float b) {
bar(a);
do_something(b);
foo();
}
int func(int a, float b, char c) {
bar(a);
do_something(b, c);
foo();
}
I see that the functionality within func
is almost the same except which version of do_something
gets called. 我看到
func
中的功能几乎相同,除了调用了哪个版本的do_something
。 Is there any way I can make this generic and combine all func
's together? 有什么办法可以使这个泛型并将所有
func
组合在一起?
To begin with, make func
a template that accepts a parameter pack. 首先,将
func
接受参数包的模板。 The int a
argument, the call to bar
and the call to foo
are always there, so that's simple. int a
参数,对bar
的调用和对foo
的调用始终存在,因此很简单。 Let's add a placeholder for do_something
for now. 现在,为
do_something
添加一个占位符。
template <class ...Args>
int func(int a, Args&&... other)
{
bar(a);
// somehow call do_something and do the right thing
foo();
return 0;
}
You want to instantiate and invoke the above template as before: 您要像以前一样实例化并调用上述模板:
func(42);
func(42, 1.f);
func(42, 1.f, 'A');
Now let's tackle the call to do_something
. 现在,让我们处理对
do_something
的调用。 If you simply add it in the middle of the new func
template; 如果您只是将其添加到新
func
模板的中间, func
do_something(std::forward<Args>(other)...);
this refuses to compile for func(42)
, ie, the case with only one argument. 这拒绝为
func(42)
编译,即只有一个参数的情况。 Hence, we need a special case for this. 因此,我们需要为此提供特殊情况。 One way to achieve this in another level of indirection for
do_something
: 在
do_something
另一个间接级别中实现此目标的一种方法:
// No additional argument case, does nothing:
void do_something_wrapper() {}
// The other two cases
template <class ...Args>
void do_something_wrapper(Args&&... args)
{
do_something(std::forward<Args>(args)...);
}
And now, the placeholder from the func
function template should be: 现在,
func
函数模板中的占位符应为:
do_something_wrapper(std::forward<Args>(other)...);
The first step would be to use variadic-templates to take the part you want to forward to do_something
: 第一步将使用可变参数模板来完成您要转发到
do_something
:
template<class ... Args>
int func(int a, Args... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
But now you have lost the argument types of func. 但是现在您已经失去了func的参数类型。 So if this is a problem you will have to find a way to test them again.
因此,如果这是一个问题,您将必须找到一种方法来再次测试它们。
Although I would probably go with the answer from generic_opto_guy myself, he's right to point out that you would lose the types in your interface. 尽管我本人可能会回答generic_opto_guy的答案,但他是正确的指出您会丢失界面中的类型。 Depending on your situation, you might want to preserve this.
根据您的情况,您可能需要保留此设置。
In that case, you can easily rework it to something akin to the following: 在这种情况下,您可以轻松地将其重新整理为类似于以下内容的内容:
namespace details {
template<class ... Args>
int func_impl(int a, Args &&... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
}
int func(int a) { return details::func_impl(a); }
int func(int a, float b) { return details::func_impl(a, b); }
int func(int a, float b, char c) { return details::func_impl(a, b, c); }
Note that the implementation has been adjusted to use perfect forwarding . 请注意,已对实现进行了调整,以使用完美转发 。 While not required in this particular case, it is often useful in forwarding situations you might encounter in the future.
尽管在这种特定情况下不是必需的,但在将来可能遇到的转发情况下,它通常很有用。
Again, unless you absolutely need to present a clear interface to client code, I would just go with the first implementation. 同样,除非您绝对需要提供一个清晰的客户端代码接口,否则我将只使用第一个实现。
The other answers are good general purpose answers to the question as asked, but if you have a few "spare" values of c
available, you could write something like: 其他答案是所问问题的通用回答,但是,如果您有几个可用的
c
备用值,则可以这样编写:
int func(int a) {
func(a, 0.0,'\001');
}
int func(int a, float b, char c = '\002') {
bar(a);
switch (c) {
case '\001':
break; // func(a)
case '\002':
do_something(b): // func(a, b)
break;
default:
do_something(b, c); // func(a, b, c)
break;
}
foo();
}
Depending on the application, this may be simpler. 根据应用程序,这可能会更简单。
Is too late to play? 玩太晚了吗?
You tagged C++14 but, if you could use C++17, you could use if constexpr
so 您标记了C ++ 14,但是,如果可以使用C ++ 17,则可以使用
if constexpr
因此
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
if constexpr ( sizeof...(Ts) > 0u )
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
In C++14 you have to duplicate something somewhere. 在C ++ 14中,您必须在某处复制某些内容。
Or you write two func()
s 或者您编写两个
func()
int func (int a)
{
bar(a);
foo();
// and remember to return something of int
}
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
or you add a no-argument do_something()
或添加无参数
do_something()
void do_something ()
{ }
or, as suggested by lubgr, you call do_something()
through a wrapper (creating a special no-argument wrapper). 或者,根据lubgr的建议,您可以通过包装器调用
do_something()
(创建一个特殊的无参数包装器)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.