我有一个简单的课程:
class A {
public:
bool f(int* status = nullptr) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
int main() {
A a;
a.f(); // <- Ambiguity is here! I want to call 'void f()'
}
Run Code Online (Sandbox Code Playgroud)
我想通过任何方式解决方法调用的歧义,转而使用异常抛出方法.
这种界面背后的基本原理:
noexcept(true)和noexcept(false)界面,noexcept(false)变量中的指针选择性地获取额外信息- 而noexcept(true)变体将始终将此信息打包在异常中.有可能吗?建议您建立更好的界面.
bol*_*lov 41
你已经发现,拥有这种签名的功能显然是一个糟糕的设计.真正的解决方案是为它们设置不同的名称或丢失默认参数,并已在其他答案中提供.
但是,如果你坚持使用界面,你不能改变或只是为了它的乐趣,这里是你如何明确地调用void f():
诀窍是使用函数指针转换来解决歧义:
a.f(); // <- ambiguity is here! I want to call 'void f()'
(a.*(static_cast<void (A::*)()>(&A::f)))(); // yep... that's the syntax... yeah...
Run Code Online (Sandbox Code Playgroud)
好的,所以它有效,但不要写这样的代码!
有一些方法可以使它更具可读性.
// create a method pointer:
auto f_void = static_cast<void (A::*)()>(&A::f);
// the call is much much better, but still not as simple as `a.f()`
(a.*f_void)();
Run Code Online (Sandbox Code Playgroud)
auto f_void = [] (A& a)
{
auto f_void = static_cast<void (A::*)()>(&A::f);
(a.*f_void)();
};
// or
void f_void(A& a)
{
auto f_void = static_cast<void (A::*)()>(&A::f);
(a.*f_void)();
};
f_void(a);
Run Code Online (Sandbox Code Playgroud)
我不知道这是否有必要更好.调用语法肯定更简单,但是当我们从方法调用语法切换到自由函数调用语法时,它可能会令人困惑.
Gui*_*let 28
两个版本f都有不同的含义.
它们应该有两个不同的名称,如:
f 对于投掷者来说,因为使用它意味着你对成功充满信心,失败将成为程序中的一个例外.try_f()或者tryF()基于错误返回的,因为使用它意味着调用失败是预期的结果.两个不同的含义应该在设计中反映出两个不同的名称.
dav*_*mac 15
因为对我来说这似乎是显而易见的,我可能会遗漏某些东西或者可能无法完全理解你的问题.但是,我认为这完全符合您的要求:
#include <utility>
class A {
public:
bool f(int* status) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
int main() {
A a;
a.f(); // <- now calls 'void f()'
a.f(nullptr); // calls 'bool f(int *)'
}
Run Code Online (Sandbox Code Playgroud)
我只是从noexcept变体中删除了默认参数.它仍然可以noexcept通过nullptr作为参数传递来调用变体,这似乎是一种非常好的方式,表明你想要调用该函数的特定变体 - 毕竟,必须有一些语法标记来指示你想要的变体打电话!
我同意其他用户的建议,只需删除默认参数.
支持这种设计的一个有力论据是,它将与新的C++ 17文件系统库保持一致,其功能通常为调用者提供异常和错误引用参数之间的选择.
例如std::filesystem::file_size,参见哪个有两个重载,其中一个是noexcept:
Run Code Online (Sandbox Code Playgroud)std::uintmax_t file_size( const std::filesystem::path& p ); std::uintmax_t file_size( const std::filesystem::path& p, std::error_code& ec ) noexcept;
除了默认参数之外,这个设计背后的想法(最初来自Boost.Filesystem)几乎与你的相同.删除它,你就像标准库的一个全新的组件,显然可以预期不会有完全破坏的设计.
| 归档时间: |
|
| 查看次数: |
3724 次 |
| 最近记录: |