c++ - 如何在不重复代码的情况下转发到两个重载之一?
问题描述
我有一个带有两个私有方法重载的 C++ 类,它们应该连接到公共方法的两个重载。
公共方法在两个重载中是相同的,只是它调用的私有方法的重载不同。另一方面,这两个私有方法重载是完全不同的,这就是我选择重载它们的原因。
为了避免在公共方法中重复代码,这似乎是完美转发的一个很好的用例。但另一方面,如果您想调用公共方法并且不熟悉 API,则很难看出您必须提供哪些参数;您必须检查公共方法的主体,然后查阅私有接口以查看存在哪些私有方法的重载。
我试图制作一个玩具类来说明我的问题:
class Foo {
public:
struct DontCopyTheBaz {};
private:
bool init_from_baz(Baz& a_baz);
bool init_from_baz(Baz& a_baz, DontCopyTheBaz);
public:
// ...should I use perfect forwarding, making the API not easily readable?
template<typename... Args>
static Foo* new_for_baz(Baz& a_baz, Args&&... args) {
Foo* the_foo = new Foo();
if (!the_foo->init_from_baz(a_baz, std::forward<Args>(args)...)) {
delete the_foo;
return nullptr;
}
return the_foo;
}
// ...or should I write duplicated code?
static Foo* new_for_baz(Baz& a_baz) {
Foo* the_foo = new Foo();
if (!the_foo->init_from_baz(a_baz)) {
delete the_foo;
return nullptr;
}
return the_foo;
}
static Foo* new_for_baz(Baz& a_baz, DontCopyTheBaz no_copy) {
Foo* the_foo = new Foo();
if (!the_foo->init_from_baz(a_baz, no_copy)) {
delete the_foo;
return nullptr;
}
return the_foo;
}
};
(实际上,私有方法和公共方法都更长更复杂。)
有没有办法避免代码重复,同时仍然使 API 易于理解?
解决方案
您可以添加额外的间接来分解代码并拥有干净的界面:
class Foo {
public:
struct DontCopyTheBaz {};
private:
bool init_from_baz(Baz& a_baz);
bool init_from_baz(Baz& a_baz, DontCopyTheBaz);
template<typename... Args>
static std::unique_ptr<Foo> new_for_baz_impl(Baz& a_baz, Args&&... args) {
auto the_foo = std::make_unique<Foo>();
if (!the_foo->init_from_baz(a_baz, std::forward<Args>(args)...)) {
return nullptr;
}
return the_foo;
}
public:
static std::unique_ptr<Foo> new_for_baz(Baz& a_baz) {
return new_for_baz_impl(a_baz);
}
static std::unique_ptr<Foo> new_for_baz(Baz& a_baz, DontCopyTheBaz no_copy) {
return new_for_baz_impl(a_baz, no_copy);
}
};
推荐阅读
- android - 应用程序中的 JNI 检测到错误:Mapbox android SDK 中的空指针
- c# - Xamarin Android Using Handler 随机崩溃无法从本机句柄激活 Java.Lang.Thread+RunnableImplementor 类型的实例
- docker - docker-compose 规模可预测的端口分配
- c# - Tuesechkin 响应时间长,返回 null
- node.js - SSD 与 HDD 作为 npm 配置中的性能因素:在哪里放置 .npm 缓存和 node_modules 目录以获得最佳性能?
- c# - CefSharp.Winform - 发送到 Web 表单输入控件时重复输入键盘键
- android-sdk-tools - Android SDK Manager Package Installation getting java.net.SocketException: Connection reset
- php - 如何在 Mysql 中存储 NULL 日期
- cakephp-3.0 - 页面上有多个表单时CakePHP CSRF令牌不匹配
- javascript - 如何从 Safari 钥匙串自动填充调用 ajax respond() 方法到服务器?