Рассмотрим следующий код:
#include <iostream>
#include <functional>
int main() {
auto run = [](auto&& f, auto&& arg) {
f(std::forward<decltype(arg)>(arg));
};
auto foo = [](int &x) {};
int var;
auto run_foo = std::bind(run, foo, var);
run_foo();
return 0;
}
Что дает компиляционная ошибка при компиляции с clang:
$ clang++ -std=c++14 my_test.cpp
my_test.cpp:6:9: error: no matching function for call to object of type 'const (lambda at my_test.cpp:8:16)'
f(std::forward<decltype(arg)>(arg));
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../include/c++/6.3.1/functional:998:14: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<const (lambda at my_test.cpp:8:16) &, const int &>' requested here
= decltype( std::declval<typename enable_if<(sizeof...(_Args) >= 0),
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../include/c++/6.3.1/functional:1003:2: note: in instantiation of default argument for 'operator()<>' required here
operator()(_Args&&... __args) const
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my_test.cpp:11:12: note: while substituting deduced template arguments into function template 'operator()' [with _Args = <>, _Result = (no value)]
run_foo();
^
my_test.cpp:8:16: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
auto foo = [](int &x) {};
^
my_test.cpp:8:16: note: conversion candidate of type 'void (*)(int &)'
1 error generated.
Почему arg
выводится как const int&
вместо int&
?
std:: bind документация говорит:
Учитывая объект g, полученный из более раннего вызова bind, когда он вызывается в выражении функции g (u1, u2,... uM), вызове хранимого объекта происходит, как если бы по std:: invoke (fd, std:: forward (v1), std:: forward (v2),..., std:: forward (vN)), где fd - значение типа std:: decay_t значения и типы связанных аргументов v1, v2,..., vN определены как указано ниже.
...
В противном случае обычный хранимый аргумент arg передается вызывающему объекту как аргумент lvalue: аргумент vn в вызове std:: invoke выше просто arg и соответствующий тип Vn является T cv &, где cv - такая же cv-квалификация, как и у g.
Но в этом случае run_foo
cv-unqualified. Что мне не хватает?