В итоге: это не ошибка компилятора.MSVC принимает этот код из-за его несоответствующего по умолчанию поведения, но его можно сделать стандартным с помощью переключателя.
Прежде всего, мне нужно уточнить один аспект std::function
: он принимаетфункция (обычно Callable ), сигнатура которой не является идеальным совпадением, но параметры могут быть преобразованы.Рассмотрим:
using intFn = void (int);
void fn(short);
intFn *a = fn; // doesn't compile
std::function<intFn> b = fn; // compiles!
Здесь intFn
тип функции, который имеет параметр int
, а функция fn
имеет параметр short
.Указатель простой функции a
не может быть установлен на fn
, так как тип параметра отличается (int
против short
).Но std::function
позволяет это, поэтому b
может быть установлен на fn
.
В вашем примере std::function
имеет параметр InputStruct
по значению, в то время как лямбда не имеет-const lvalue ссылка InputStruct &
.Когда std::function
std::forward
s его параметр, он становится значением xvalue, которое не может быть привязано к ссылочному параметру lvalue лямбды.Вот почему стандартные соответствующие компиляторы не принимают этот код.
Почему MSVC принимает этот код?Поскольку он по умолчанию имеет несоответствующее поведение: он позволяет привязывать временные классы (и значения x) к неконстантным ссылкам lvalue.Вы можете отключить это поведение с помощью /Zc:referenceBinding
(или более старой опции /Za
).Если вы используете этот переключатель, MSVC отклонит ваш пример.