我正在尝试设计一个像这样的简单函数:
void draw(Callback callback)
{
Drawing drawing("name");
callback(drawing);
std::cout << drawing.name() << std::endl;
}
其中
drawing
应作为引用传递给回调,以便调用者可以像这样修改它:
draw([](auto& drawing) {
drawing.set_name("another name");
});
现在这可以工作了,因为我明确地将回调参数输入为
auto&
(或 Drawing&
)。
但是,当我仅将参数键入为 auto
(或 Drawing
)时,代码也会编译,但不再按预期工作。 drawing
实例是复制的,而不是通过引用传递的。
当 lambda 参数未显式键入为引用时,我希望代码不再编译。
我尝试过以下方法:
using Callback = std::function<void(Drawing&)>;
:未明确输入为 drawing
时,auto&
不会被修改。template<typename T> concept Callback = std::is_invocable<void, T, Drawing&>;
:同上。using Callback = void (*)(Drawing&);
:这确实有效,但我失去了使用捕获的能力。那么我该如何正确输入 Callback,以便只有
Drawing&
才是 lambda 的有效参数?
您可以约束
draw
,以便不能使用右值调用它:
template <typename Callback>
requires (std::invocable<Callback, Drawing&> && !std::invocable<Callback, Drawing&&>)
void draw(Callback callback)
{
Drawing drawing("name");
callback(drawing);
std::cout << drawing.name() << std::endl;
}
如果给定的
callback
接受auto
或auto&&
,它将不满足约束:
int main() {
draw([](auto& drawing) {}); // OK
draw([](auto drawing) {}); // error: no matching function call ...
}
请参阅编译器资源管理器中的实时示例。