предотвратить возврат типа возврата лямбда - PullRequest
3 голосов
/ 23 октября 2019

Приведенный ниже код не может быть скомпилирован из-за автоматического вывода типа, возвращаемого лямбда-выражением.

Как правильно предотвратить этот вывод в синтаксических терминах C ++ 14 без завершающего типа?

Ошибка компиляции из-за несовместимого типа (rvalue) на входе test (), который ожидает неконстантную ссылку

struct B {
    int i;
};

struct A {
    B &getB() { return b; }
private:
    B b;
};

void test(B &b)  {
    b.i++;
}

int main() {
    A a;

    test([&a]() { 
        return a.getB();
    });
    return 0;
}

1 Ответ

7 голосов
/ 23 октября 2019

Здесь есть две проблемы.


Во-первых, вы на самом деле не вызываете лямбду, поэтому вместо передачи возвращенного значения в test вы передаете объект функции, который явносовершенно несовместимый тип! Решите это, добавив () после лямбда-выражения для его вызова, передав таким образом возвращаемое значение test().

[](){ return 42; } ();
//                 ^^ now the whole expression has value 42

Во-вторых, вы правы, выведенный тип возврата будет B, а не B&, и временный объект может быть не привязан к аргументу ref-to-non- const test(B&).

Одним из способов решения этой проблемы является использование конечного возвращаемого типачтобы вызвать ссылку:

    [&a]() -> B& { .... }

Вы, кажется, знаете это, но не хотите этого делать. Почему?

Другой вариант - вернуть справочную оболочку, которая затем возвращается по значению, но ведет себя как ссылка:

return std::ref(a.getB()));

Другой вариант - изменить testчтобы иметь возможность принять какое-то временное. Поскольку вам нужно это, чтобы иметь возможность изменять исходный объект, вы можете иметь test взять указатель или другой тип со ссылочной семантикой (умный указатель, std::reference_wrapper<B>, make B имеют ссылочную семантику при копировании, ...)

void test(B* b) {
    ++(b->i);
}
...
test([&]() { return &a.getB(); } () );

Примечание для педантов: я знаю, что парены в ++(b->i) не являются строго необходимыми. Я нахожу это более ясным.

...