2016-09-04 5 views
1

Я пытаюсь воспроизвести API потоков Java на C++ и сделал эту программу до сих пор.C++ lambdas, "error: expected expression"

#include <iostream> 

using namespace std; 

template <typename E> 
class stream { 
    virtual void collect(void (*consumer) (E)) = 0; 
    virtual bool anyMatch(bool (*predicate) (E)) { 
     bool found = false; 
     collect([&found](E obj) -> { if (predicate(obj)) {found = true} }); 
     return found; 
    } 
}; 

int main() { 
    return 0; 
} 

Но когда я пытаюсь скомпилировать его с г ++:

enter image description here

Что я делаю неправильно лямбда? Предполагается предоставить функцию (потребитель), которая проверит данный E с предикатом (функцией), и если он даст значение true, установите значение true.

+0

Это не лениво. Одно из главных преимуществ потоков над стандартными алгоритмами (* cough * 'std :: accumulate',' std :: any_of') состоит в том, что они ленивы. Для этого уже есть библиотеки, такие как range-v3, которые в какой-то момент должны стать стандартными. – chris

+0

Да, я просто стараюсь учиться C++ – Phoenix

+3

Только lambdas без захватов конвертируются в простые указатели функций. Лямбда с захватами не может этого сделать - у нее не будет места для хранения этих снимков. –

ответ

1

Есть несколько отдельных вопросов в вашем коде:

  1. Ошибка вы вывесили предполагает, что вы собираете в режиме предварительного C++ 11. Lambdas были представлены на C++ 11.

  2. Существует несколько синтаксических ошибок. В вашем типе возвращаемого возврата лямбда отсутствует тип, и вам не хватает точки с запятой в теле лямбда.

  3. Вы пытаетесь преобразовать безлокадную лямбду в указатель функции. Это невозможно, так как для захвата переменных требуется состояние/контекст.


Ваш код не действует C++ - синтаксис неверен. Вот a version with valid syntax:

template <typename E> 
class stream 
{ 
    virtual void collect(void (*consumer)(E)) = 0; 
    virtual bool anyMatch(bool (*predicate)(E)) 
    { 
     bool found = false; 
     collect([predicate, &found](E obj) 
      { 
       if(predicate(obj))      
        found = true;      
      }); 

     return found; 
    } 
}; 

Тем не менее, код не будет компилироваться, так без captureless лямбды не могут быть преобразованы в указатели на функции. Если это будет разрешено, это будет рецепт катастрофы, так как информация о захваченных переменных будет потеряна. You can instead use std::function, который стирает тип лямбды и работает с непустыми списками захвата, за счет памяти/накладные расходы времени выполнения:

template <typename E> 
class stream 
{ 
    virtual void collect(std::function<void(E)> consumer) 
    { 
     (void)consumer; 
    } 

    virtual bool anyMatch(std::function<bool(E)> predicate) 
    { 
     bool found = false; 
     collect([predicate, &found](E obj) 
      { 
       if(predicate(obj))      
        found = true;      
      }); 

     return found; 
    } 
}; 
+0

Он компилируется только потому, что вы фактически не создаете экземпляр 'stream'. [Как только вы это сделаете, он не сработает) (http://rextester.com/LYRBD37125). –

+0

@IgorTandetnik: да - «компилирует» я имел в виду «правильный/синтаксический синтаксический анализ Си ++». Я уточню ответ –

+0

@IgorTandetnik: Я улучшил ответ. Дайте мне знать, если он все еще вводит в заблуждение –

0

Текст ошибки наводит на мысль, что ваш компилятор не поддерживает C++ 11 , или не работает в режиме C++ 11.

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

Обновите свой компилятор, предоставив -std=c++11 в командной строке, если это необходимо.

+1

'[] (int obj) -> {(void) obj; } 'недействителен лямбда-синтаксис. Тип необходим после '->', если явно указан тип возвращаемого типа * *. –