我正在使用C++14 (而且对它非常陌生)。我有3个重载函数func,根据其父函数(func)调用另一个重载函数do_something。
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();
}我看到func中的功能几乎是相同的,只是调用了哪个版本的do_something。有什么方法可以使这个通用化并将所有的func合并在一起吗?
发布于 2019-07-16 09:04:53
首先,让func成为一个接受参数包的模板。int a参数、对bar的调用和对foo的调用总是存在的,所以这很简单。现在让我们为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;
}您希望像前面一样实例化和调用上面的模板:
func(42);
func(42, 1.f);
func(42, 1.f, 'A');现在,让我们来处理对do_something的调用。如果简单地将其添加到新的func模板的中间;
do_something(std::forward<Args>(other)...);这拒绝为func(42)编译,即只有一个参数的情况。因此,我们需要一个特例来解决这个问题。在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)...);
}现在,func函数模板的占位符应该是:
do_something_wrapper(std::forward<Args>(other)...);发布于 2019-07-16 08:58:49
第一步是使用各种模板来获取您想要转发到do_something的部分。
template<class ... Args>
int func(int a, Args... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}但是现在你已经失去了func的论证类型。因此,如果这是一个问题,你将不得不找到一个方法来再次测试他们。
发布于 2019-07-16 09:08:17
虽然我可能会从generic_opto_guy本人那里得到答案,但他指出,您将失去接口中的类型,这是正确的。根据您的情况,您可能需要保留这个。
在这种情况下,您可以轻松地将其重新工作到类似于以下内容:
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); }注意,实现已经调整为使用完美转发。虽然在这种特殊情况下不需要,但它在转发将来可能遇到的情况时通常是有用的。
同样,除非您绝对需要向客户端代码提供一个清晰的接口,否则我将只使用第一个实现。
https://stackoverflow.com/questions/57053519
复制相似问题