如果参数不是引用,如何防止编译通过的lambda

Ale*_*ph0 3 c++ lambda closures std-function

在我的一个项目中,我正在使用一个小的实用程序函数,该函数带有一个Message结构和一个lambda函数,用于修改此消息结构。

现在,我无意间通过了一个lambda,而没有必要的引用&。它可以完美地编译,但没有提供所需的输出。

对于我来说,应该有以下两种行为之一:

  1. 忘记写了auto&,但是auto应该导致编译错误
  2. 写作auto应该被解释为auto&。

是否可以防止在丢失的情况下编译,&甚至更好地将其解释auto为auto&自动?

#include <iostream>
#include <functional>
#include <boost/variant.hpp>

struct Message {
    int x;
    int y;
};

void changeMessage(Message& m, const std::function<void(Message&)>& messageModifier) {
    std::cout << "Message before:" << m.x << " " << m.y << "\n";
    messageModifier(m);
    std::cout << "Message after:" << m.x << " " << m.y << "\n";
}

int main(int, char**) {
    {
        std::function<void(int&)> f = [](int&) {};
        std::function<void(int)> g = [](int) {};
        f = g; // This compiles. 
    }

    {
        std::function<void(int&)> f = [](int&) {};
        std::function<void(int)> g = [](int) {};
        //g = f; // This does not compile. Makes perfect sense.
    }

    Message m{ 10,20 };
    {
        changeMessage(m, [](auto m) { m.x++; m.y--; }); // User unintentionally forgot &! Can I prevent this from compilation?
        std::cout << "Message outside: " << m.x << " " << m.y << "\n";
    }
    {
        changeMessage(m, [](auto& m) { m.x++; m.y--; });
        std::cout << "Message outside: " << m.x << " " << m.y << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

Evg*_*Evg 5

防止Message按值传递(并且auto它本身永远不是引用)的一种方法是禁用复制构造:

struct Message {
    Message() = default;
    Message(const Message&) = delete;

    int x;
    int y;
};
Run Code Online (Sandbox Code Playgroud)

@ LF建议的另一个解决方案是检查lambda不接受右值:

template<class Fn>
void change_message(Message& m, Fn fn) {
    static_assert(!std::is_invocable_v<Fn, Message&&>);     
    fn(m);
}
Run Code Online (Sandbox Code Playgroud)

  • @Fureeish,未使用的* named *变量。 (2认同)