C ++ 0x и лямбды - PullRequest
       21

C ++ 0x и лямбды

2 голосов
/ 12 ноября 2011

Посмотрите на этот шаблон:

template <class T>
auto checkErrorCode(T& functor) -> decltype(functor()) {
    auto retCode = functor();
    // ... additional aspect-like stuff with retCode here
    return retCode;
}

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

Даже если он компилируется и отлично работает с этим ...

int foo(int param)
{
    return param>10?0:-1;
}

main()
{
    int param = 11;

    // This compiles fine
    auto action = [&](){ return foo(param); };
    checkErrorCode( action );
}

... он не компилируется - и генерируетчтобы понять ошибку - когда я напрямую вызываю "checkErrorCode" со встроенной лямбдой:

int foo(int param)
{
    return param>10?0:-1;
}

main()
{
    int param = 11;

    // This doesn't compile...
    checkErrorCode( [&](){ return foo(param); } );
}

Есть мысли о том, почему?

g ++ выдает эту странную ошибку:

forSO.cpp: In function 'int main()':
forSO.cpp:24:5: error: no matching function for call to 'checkErrorCode(main()::<lambda()>)'
forSO.cpp:24:5: note: candidate is:
forSO.cpp:2:6: note: decltype (functor()) checkErrorCode(T&) [with T = main()::<lambda()>, decltype (functor()) = int]
forSO.cpp:2:6: note:   no known conversion for argument 1 from 'main()::<lambda()>' to 'main()::<lambda()>&'

В маловероятном случае, если это ошибка компилятора:

bash$ g++ -v
...
gcc version 4.6.2 (GCC) 

1 Ответ

4 голосов
/ 12 ноября 2011

В шаблоне необходимо использовать ссылку rvalue:

template <class T>
auto checkErrorCode(T&& functor) -> decltype(functor()) {
    auto retCode = functor();
    // ... additional aspect-like stuff with retCode here
    return retCode;
}

или const lvalue (const T&).Поскольку лямбда-выражения являются временными (rvalue) функциями, вы можете передавать их только по ссылке const (lvalue) или по ссылке rvalue.

Как правило, сохраняйте lvalue refs const, если вы не планируете осуществлять неконстантный доступ (напримерлевая сторона присваивания, вызов неконстантной функции-члена и т. д.) Если вы делаете продолжения, это может быть немного сложнее, потому что тогда вам придется передавать неконстантную ссылку на lvalue.Но у вас был бы явный класс функторов, поэтому неконстантное создание ссылки на lvalue разрешено.В этом случае проще использовать rvalue ref для лямбда-выражений, так как const lvalue ref - это способ работы C ++ 98, и ограничения этой системы были мотивирующим фактором для создания ссылок на rvalue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...