Я немного покопался, и мне кажется, что ответ немного более детальный, чем кажется из некоторых комментариев.
Сначала есть этот ответ на более ранний ответ. вопрос . Процитируем важную часть:
[C++11: 5.1.2/14]:
Сущность захвачена копией , если она неявно захвачена и capture-default равен =
или , если он явно захвачен захватом, который не включает &
. Для каждого объекта, захваченного копией, в закрывающем типе объявляется неназванный элемент данных, не содержащий данных c. Порядок объявления этих членов не уточняется. Тип такого элемента данных - это тип соответствующего захваченного объекта, если объект не является ссылкой на объект, или ссылочный тип в противном случае. [..]
Тогда есть этот ответ на другой вопрос . Снова цитата:
5 Тип закрытия для лямбда-выражения не универсального c имеет открытый оператор вызова встроенной функции [...] Этот оператор вызова функции или шаблон оператора объявляется const
(9.3.1) в том и только в том случае, если условие-объявления-выражения лямбда-выражения не сопровождается mutable
.
I тогда соберите это вместе в небольшом тесте:
#include <iostream>
using std::cout;
using std::endl;
void foo(const std::string&) {
cout << "void foo(const std::string&)" << endl;
}
void foo(std::string&) {
cout << "void (std::string&)" << endl;
}
struct klaf
{
std::string b;
void bla() const
{
cout << std::boolalpha << std::is_const<decltype(b)>::value << endl;
foo(b);
}
};
int main()
{
klaf k;
k.bla();
std::string s;
const std::string s2;
auto lam = [=]() {
cout << std::boolalpha << std::is_const<decltype(s)>::value << endl;
foo(s);
cout << std::boolalpha << std::is_const<decltype(s2)>::value << endl;
foo(s2);
};
lam();
}
Какие выходы (и выходы одинаковы в G CC, Clang и MSV C):
false
void foo(const std::string&)
false
void foo(const std::string&)
true
void foo(const std::string&)
klaf::b
(очевидно) не const
, но поскольку функция klaf::bla
равна const
, то klaf::b
рассматривается как const
при вызове foo
.
То же самое Значение true в lam
, где s
фиксируется значением со значением std::string
. Однако s2
был объявлен как const std::string
, и это относится к типу элемента данных в лямбда-выражении.
Вкратце: захват по значению в лямбда-выражении не сделайте сам захваченный элемент const
, но, поскольку operator()
для лямбды равно const
, тогда члены повышаются до const
в этой функции (если лямбда не объявлена изменяемой).
EDIT :
Вдохновленный комментариями @arnes, я обнаружил разницу в G CC и Clang:
int main()
{
int i = 12;
auto lam = [=, ic = i]() {
cout << std::boolalpha << std::is_const<decltype(i)>::value << endl;
cout << std::boolalpha << std::is_const<decltype(ic)>::value << endl;
};
lam();
}
Это дает false false
в Clang, но false true
в G CC. Другими словами, захват с инициализатором становится const
в G CC, но не в Clang.