在我的一个项目中,我正在使用一个小的实用程序函数,该函数带有一个Message
结构和一个lambda函数,可以修改此消息结构。
现在,我无意中通过了一个lambda,而没有必要的引用&。它可以完美地编译,但没有提供所需的输出。
对于我来说,应该有以下两种行为之一:
auto&
,但是仅仅auto
会导致编译错误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";
}
}
答案 0 :(得分:5)
一种防止按值传递Message
(并且auto
本身从不引用)的一种方法是禁用复制构造:
struct Message {
Message() = default;
Message(const Message&) = delete;
int x;
int y;
};
@ L. F.建议的另一种解决方案是检查lambda不接受右值:
template<class Fn>
void change_message(Message& m, Fn fn) {
static_assert(!std::is_invocable_v<Fn, Message&&>);
fn(m);
}