如何限制lambda参数的参数只能是引用?

问题描述 投票:0回答:1

我正在尝试设计一个像这样的简单函数:

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 的有效参数?

c++ c++20 c++-concepts
1个回答
1
投票

您可以约束

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 ...
}

请参阅编译器资源管理器中的实时示例

© www.soinside.com 2019 - 2024. All rights reserved.