【发布时间】:2021-05-13 22:36:07
【问题描述】:
我正在尝试创建一个基类,用于围绕各种作用域操作创建帮助器,为此,基类允许分配可调用对象。一个简单的谓词确定是否调用了可调用对象。无论如何,总是调用 dtor。
问题是每个派生类都需要显式继承 operator=。有没有办法编写基类,这样就不需要了?
#include <functional>
#include <iostream>
using callback_t = std::function<void(void)>;
struct C
{
constexpr C(bool ok) : ok_{ok} {}
bool ok_ {false};
bool operator=(callback_t fn) const noexcept {
return ok_ ? fn(), true : false;
}
~C() noexcept {
std::cout << "end\n";
}
};
struct D final : public C
{
using C::operator=;
};
int main()
{
auto predicate = [] { return true; };
D{predicate()} = [] {
std::cout << "ok\n";
};
D{false} = [] {
std::cout << "wrong\n";
};
}
(也是https://gcc.godbolt.org/z/eh8ncffos)
从struct D中删除行
using C::operator=;
导致编译错误,因为Ds 默认的复制操作符抢占了 C 的自定义操作符=。
<source>: In function 'int main()':
<source>:24:9: error: no match for 'operator=' (operand types are 'D' and 'main()::<lambda()>')
24 | };
| ^
<source>:14:12: note: candidate: 'constexpr D& D::operator=(const D&)'
14 | struct D final : public C
| ^
<source>:14:12: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const D&'
<source>:14:12: note: candidate: 'constexpr D& D::operator=(D&&)'
<source>:14:12: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'D&&'
<source>:27:9: error: no match for 'operator=' (operand types are 'D' and 'main()::<lambda()>')
27 | };
| ^
<source>:14:12: note: candidate: 'constexpr D& D::operator=(const D&)'
14 | struct D final : public C
| ^
<source>:14:12: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const D&'
<source>:14:12: note: candidate: 'constexpr D& D::operator=(D&&)'
<source>:14:12: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'D&&'
【问题讨论】:
-
尝试使用 CRTP 吗?
-
@IgorR。如果它只是默认的 operator=,我会这样做,但这是一个转换运算符,我似乎无法通过 crtp 实现这一点:gcc.godbolt.org/z/neKGzK8oa
-
一定要拼写
operator=吗?而不是喜欢...call? -
@Barry Blame boost/ut; tldr 我们不想在传递给它的 lambda 周围添加括号。它被用作一种通用范围包装器/延迟机制:gcc.godbolt.org/z/E8hhrxhd3
-
@Barry(考虑到条件执行,我更喜欢 'operator&&',但我仍然想知道它可以通过 operator= 来实现,而不需要 'using' 术语)