Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > std::list::remove_if и лямбда-выражение


Автор: Fynivx 9.3.2012, 06:59
Здравствуйте. У меня возникла следующая проблема:
необходимо удалить элементы из списка по условию.

Вот это:
Код

void EventEmitter::off ( std::string event_name, v8::Handle<v8::Function> listener ) {
//event_map - экземпляр класса map< std::string, list< v8::Handle< v8::Function > > >
    event_map.at( event_name ).remove_if(
        [ listener ] ( const v8::Handle< v8::Function > current ) {
            return current == listener;
        }
    );
}

при компиляции в clang выдает ошибку "expected expression" на первой квадратной скобке.
При компиляции в gcc говорит, что необходимо указать тип предиката в шаблоне remove_if. Но какой тип нужно указать - я не знаю.

Функция приобретает работоспособность, если сделать так:
Код

class __function_equal_predicate {
public:
    __function_equal_predicate ( v8::Handle< v8::Function > listener ) {
        __listener = listener;
    }
    ~__function_equal_predicate ( void ) {  }
    bool operator() ( const v8::Handle< v8::Function >& current ) {
        return current == __listener;
    }
private:
    v8::Handle<v8::Function> __listener;
};

void EventEmitter::off ( std::string event_name, v8::Handle< v8::Function > listener ) {
    __function_equal_predicate predicate( listener );
    event_map.at( event_name ).remove_if( predicate );
}

Но это плохой, никуда не годный вариант.

Подскажите пожалуйста, что нужно сделать, чтобы первый вариант, все-таки, заработал?

Автор: borisbn 9.3.2012, 10:31
Цитата(Fynivx @  9.3.2012,  06:59 Найти цитируемый пост)
при компиляции в clang выдает ошибку "expected expression" на первой квадратной скобке.

в опциях компилятора установлено -std=c++0x ?
Цитата(Fynivx @  9.3.2012,  06:59 Найти цитируемый пост)
При компиляции в gcc говорит, что необходимо указать тип предиката

какая версия gcc ?

и ещё... конечно, не должно никак влиять, но... попробуй передавать в лямбду по ссылке
Цитата
[ listener ] ( const v8::Handle< v8::Function > & current ) {
            return current == listener;
        }

Автор: bsa 9.3.2012, 10:32
Fynivx, а ты точно включил поддержку С++11 в настройках компилятора? И вообще, версия твоего компилятора поддерживает lambda-выражения?

Автор: Fynivx 9.3.2012, 16:47
borisbn, bsa

clang - 3.0
gcc - 4.6.3

В gcc - указан стандарт c++0x (-std=c++0x)
В clang этого делать просто не нужно - он даже такого ключа не знает.

И, судя по тому, что в некоторых местах вполне успешно юзаются стандартные трэды, поддержка, все-таки, есть.

borisbn,
Да, тут нужно передавать по ссылке и, да, на результат компиляции это не повлияло.

----
Я только что посмотрел статус поддержки  11ой спецификации на сайте clang. Печально, но дело в том, что в релизе лямбды пока не поддерживаются.

Но что нужно сказать gcc, чтобы он это дело откомпилил? Шаблон должен подбираться автоматически, но этого не происходит. Видимо потому, что gcc не может определить тип лямбды. Возможно ли ему как-то с этим помочь?

Добавлено через 5 минут и 58 секунд
Вы не поверите. Я немного затупил, и не попробовал проверить это на gcc после последнего обновления.

И таки что бы вы думали?) Теперь всё компилится.) Видимо, недоработка была в нем, и в последнем обновлении ее исправили. Всем спасибо, теперь всё работает)

Ждем нового релиза clang)

Автор: boostcoder 9.3.2012, 18:04
Цитата(Fynivx @  9.3.2012,  16:47 Найти цитируемый пост)
 в релизе лямбды пока не поддерживаются

юзанье clang`а с этого и нужно начинать.

Добавлено через 44 секунды
Цитата(Fynivx @  9.3.2012,  16:47 Найти цитируемый пост)
Но что нужно сказать gcc, чтобы он это дело откомпилил?

-std=c++0x

Добавлено через 2 минуты и 43 секунды
Цитата(Fynivx @  9.3.2012,  16:47 Найти цитируемый пост)
на gcc после последнего обновления

gcc поддерживает лямбды начиная с 4.6.0

Автор: Fynivx 9.3.2012, 23:55
boostcoder,
Цитата(boostcoder @  9.3.2012,  18:04 Найти цитируемый пост)
юзанье clang`а с этого и нужно начинать.

Я с этого и начал, вообще-то.

Цитата(boostcoder @  9.3.2012,  18:04 Найти цитируемый пост)
-std=c++0x

И во втором посте написал, что изначально использовал этот флаг.


Цитата(boostcoder @  9.3.2012,  18:04 Найти цитируемый пост)
gcc поддерживает лямбды начиная с 4.6.0

а насчет лямбды он и не ругался - он не мог определить необходимый тип шаблона для нее.

Внимательнее читайте, товаристч)

Автор: mes 10.3.2012, 00:09
Цитата(Fynivx @  9.3.2012,  05:59 Найти цитируемый пост)
 gcc говорит, что необходимо указать тип предиката


list.remove_if ([..] (...) ->bool { return ... });

Автор: Fynivx 10.3.2012, 01:36
mes,

Предиката а не возвращаемого им значения. Но все-равно спасибо.

Автор: mes 10.3.2012, 10:49
Цитата(Fynivx @  10.3.2012,  00:36 Найти цитируемый пост)
Предиката а не возвращаемого им значения

тогда либо с хидерами напутали, либо глюк компилятора..

Автор: boostcoder 10.3.2012, 11:41
Цитата(Fynivx @  9.3.2012,  23:55 Найти цитируемый пост)
Я с этого и начал, вообще-то.

если бы ты с этого начинал, у тебя бы не возникло желания юзать лямбды на clang 3.0


Цитата(Fynivx @  10.3.2012,  01:36 Найти цитируемый пост)
Предиката а не возвращаемого им значения.

воспроизведи ошибку. http://liveworkspace.org/ например.

Автор: boostcoder 10.3.2012, 12:04
http://liveworkspace.org/code/29ccebe4d7b166ec07e839a12e43ba03

Автор: Fynivx 10.3.2012, 15:09
boostcoder,
Еще раз. Я с самого начала написал про два компилятора. И с самого начала написал, что каждый из них от меня хочет. После этого я сам написал, почему clang выдает синтаксическую ошибку.

Цитата(boostcoder @  10.3.2012,  11:41 Найти цитируемый пост)
воспроизведи ошибку. тут например. 

Как выбрать компилятор?

Читать посты - не царское дело. Я понимаю.

Автор: Fynivx 10.3.2012, 15:37
boostcoder
К сожалению, кэш у меня автоматически чистится, и откатить gcc я не могу. Но, если интересуют подробности, помню, что было следующее - при использовании remove_if() с предикатом-лямбдой, он не вставлял в шаблон сгенерированный тип, а подставлял тип по умолчанию. А по умолчанию в шаблоне было написано _Predicate = _Predicate. А такой тип, естественно, не подходил. Вот и все дела.

Версия gcc была 4.6.2-*, где * - не знаю, какая цифра, определяющая номер релиза пакета в дистрибутиве. Сейчас 4.6.3-1, и всё работает.
Кстати, об этом я уже тоже писал.

Автор: JackYF 11.3.2012, 12:24
Цитата(boostcoder @  9.3.2012,  17:04 Найти цитируемый пост)
gcc поддерживает лямбды начиная с 4.6.0


С 4.5.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)