Вопрос

Можно ли запечатлеть ссылку Const в выражении лямбда?

Я хочу, чтобы назначение, отмеченное ниже, например, для проваливания:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";

    for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
      {
        best_string = s; // this should fail
      }
    );
    return 0;
}

Обновлять: Поскольку это старый вопрос, можно было бы хорошо обновить его, если в C ++ есть удобства, чтобы помочь с этим. Разрешения в C ++ 14 позвольте нам захватить объект Non-Const от Consta Refect? (Август 2015 года)

Это было полезно?

Решение

const Не в грамматике для захвата как N3092:

capture:
  identifier
  & identifier
  this

Текст только упоминается только по Chapue-Copy-Copy-Capture-Resement, и не упоминает какую-либо какую-либо постоянную недвижимость.

Чувствуется как надзор для меня, но я очень внимательно следил за процессом стандартизации.

Другие советы

C ++ 14:

[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
    best_string = s; // fails
};

Демонстрация


C ++ 17:

[&best_string = std::as_const(best_string)](const string& s)
{
    best_string = s; // fails
};

Демо 2.

Я думаю, что часть захвата не должна указывать const, Как означает захват, ему нужен только способ доступа к внешней переменной области.

Спецификатор лучше указан во внешнем объеме.

const string better_string = "XXX";
[&better_string](string s) {
    better_string = s;    // error: read-only area.
}

лямбда функция это const (не может изменить значение в его объеме), поэтому при выработке переменной по значению, переменная не может быть изменена, но ссылка не находится в области лямбда.

Я думаю, что если вы не используете переменную в качестве параметра функтора функтора, вы должны использовать уровень доступа текущей функции. Если вы думаете, что не следует, то отделите лямбда от этой функции, это не его часть.

Во всяком случае, вы можете легко добиться того же, что вы хотите, используя другую ссылку Const:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";
    const string& string_processed = best_string;

    for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
    {
        string_processed = s;    // this should fail
    }
    );
    return 0;
}

Но это то же самое, что предполагает, что ваша лямбда должна быть изолирована от текущей функции, что делает ее не-лямбда.

Я думаю, у вас есть три разных варианта:

  • Не используйте ссылку Const, но используйте Copy Capture
  • игнорировать тот факт, что это модифицируется
  • Используйте STD :: BING, чтобы связать один аргумент двоичной функции, которая имеет капризную ссылку.

используя копию

Интересная часть о лямбдах с копией захвата состоит в том, что те только для чтения и, следовательно, имеют именно то, что вы хотите.

int main() {
  int a = 5;
  [a](){ a = 7; }(); // Compiler error!
}

Использование std :: bind

std::bind Уменьшает артую функции. Обратите внимание, однако, что это может / приведет к косвенному вызова функции через указатель функции.

int main() {
  int a = 5;
  std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}

Есть более короткий путь.

Обратите внимание, что нет амперсада до «Best_String».

Это будет иметь «Const std :: Type_wrapper << T >>» тип.

[best_string = cref(best_string)](const string& s)
{
    best_string = s; // fails
};

http://coliru.Stacked-crooked.com/a/0e54d6f9441e6867.

Используйте Clang или ждать, пока эта ошибка GCC не будет исправлена: ошибка 70385: захват лямбда посредством ссылки consthttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385.]

Использование Const будет просто иметь ALGORITHM AMPERSAND, установила строку к ее первоначальному значению, другими словами, лямбда на самом деле не будет определять себя в качестве параметра функции, хотя окружающий объем будет иметь дополнительную переменную ... не определяя его Хотя это не определяло бы строку как типичную & & & best_string] (String Const S) Следовательно, скорее всего, лучше, если мы просто оставемся в этом, пытаясь захватить ссылку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top