C++, std::algorithm, WTF?!

bleyman

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

typedef vector<int> Collection;

struct remove_it
{
bool operator (int item) { return item & 1; }
};

int main
{
// struct remove_it
// {
// bool operator (int item) { return item & 1; }
// };

Collection items;
items.push_back(0); items.push_back(1); items.push_back(2); items.push_back(3);

Collection::iterator it = remove_if(items.begin items.end remove_it;
items.erase(it, items.end;
for (it = items.begin; it != items.end; it++)
{
cout << *it << " ";
}
}

Компилится и работает. Если раскомментировать объявление функтора внутри, гцц говорит error: no matching function for call to 'remove_if(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, main::remove_it)'
Как так? Проверял и на довольно свежем гцц (4.2.2).

enochka1145

OMG! пишет "it++"! С миром что-то не так!
По теме: с виду неясно, gcc не использую. Заинтригован.

okunek

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

erotic

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

bleyman

Так а что делать — вообще нельзя работать с анонимными/вложенными функторами что ли?
Я же вроде видел сотни примеров где это делается!
@: я вообще все эти плюсовые заморочки тихо ненавижу, и полагаю, что это задача конпелятора их оптимизировать. ++it — уродское!

enochka1145

Твои чувства к инкрементам - дело твоё, но ты как бы посылаешь мессидж: "пацаны, а я нихера не смыслю в этих ваших префиксах/постфиксах!"

istran

К слову, на днях зарелизился gcc-4.5, в котором реализованы лямбды. В C++ уже столько сахара, что скоро попа слипнется.
upd: В этой версии стало можно использовать локальные и анонимные классы в качестве параметров шаблонов.

Serab

переносимость, батенька, если о ней не задумываться, то жопа может слипнуться, да почище, чем от сахара :(

Serab

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

erotic

Так а что делать — вообще нельзя работать с анонимными/вложенными функторами что ли?
С вложенными куда? Вроде можно в классе сделать подклассик и его использовать. По крайней мере вот это компилируется:

template <class T>
class V
{
T v;
};

class z
{
class b
{
};
V<b> bb;
};

int main
{
return 0;
}

enochka1145

Конечно, это компилируется, поскольку ничего шаблонного не инстанциируется :).
Попробуй добавить хотя бы "volatile z z0;"

doublemother

К слову, на днях зарелизился gcc-4.5
Окстись, «на днях» — это уже 4.6 зарелизился.

Maurog

Как так?
c++ 2003
9.8 Local class declarations
1 A class can be defined within a function definition; such a class is called a local class. The name of a local
class is local to its enclosing scope. The local class is in the scope of the enclosing scope, and has the same
access to names outside the function as does the enclosing function. Declarations in a local class can use
only type names, static variables, extern variables and functions, and enumerators from the enclosing
scope.
14.3.1 Template type arguments
2 A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall
not be used as a template-argument for a template type-parameter.

14.5.2 Member templates
...
2 A local class shall not have member templates.
14.5.3 Friends
...
8 A friend template shall not be declared in a local class.
c++0x : пункта 14.3.1/2 нет

istran

Ура! Теперь еще и range-based for-loop появился.

apl13

В C++ уже столько сахара, что скоро попа слипнется.
Ой, не смешите мои тапочки.

elenangel

и чем же в этом месте it++ отличается от ++it?

apl13

Сахар там если и есть, то совсем рафинированный, химической очистки.

erotic

Конечно, это компилируется, поскольку ничего шаблонного не инстанциируется :).
Попробуй добавить хотя бы "volatile z z0;"
Попробуй сначала сам добавить и собрать. У меня все ок.
Кроме того, инстанцирование происходит и без определения переменной типа z, т.к. в z указан V<b>, а b вполне себе конкретный класс, и z вполне себе конкретный класс. Если в V написать что-то типа typename T::type v;, тогда в моем примере будет ошибка.
Подытожу: ты написал необдуманную фигню.

Serab

и чем же в этом месте it++ отличается от ++it?
блин, если it — объект, то теоретически, правильно написанный it++ чутка больше действий содержит, чем ++it и даже может быть через него реализован. Так-то.

elenangel

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

Serab

ч0? там речь была о том, что это тииипа медленнее. Причем тут говнокод?

bleyman

Бля, возьми и проверь что быстрее в любом нормальном компиляторе со включённой оптимизацией.
Я проверил на vector и map в gcc — одинаково.
Я считаю недостойным своей видовой принадлежности, недостойным для носителя гордого имени Человек писать говнопрефиксный инкремент чтобы сэкономить 5% производительности в мифических говнокомпиляторах, которые не умеют производить эту тривиальную оптимизацию.

Serab

Бля, возьми и проверь что быстрее в любом нормальном компиляторе со включённой оптимизацией.
бля, возьми и посчитай, сколько букв и я употребил в слове тииииипа там в посте выше.

iravik

говнопрефиксный инкремент
а чем тебе не угодил префиксный инкремент?

slonishka

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

iravik

ну просто такая ненависть к префиксному инкременту, как будто он пишется гораздо сложнее. Тут уже больше похоже на вредность, типа: "вот тебе компилятор, я написал i++, а тебе это надо оптимизировать!"

Serab

Да там так и есть, размеры постов и риторика выдают обоих с потрохами :)

slonishka

ну просто такая ненависть к префиксному инкременту
нет ненависти, просто любит попиздеть. =)
а - попенартурить.

slonishka

ну или кто там начал этот балаган первым

slonishka

нахуя я вообще в этот форум блядь пишу опять?

iravik

ты не пиши, а то от работы отвлекаешься ;)

karkar

вы все не пишите, а то я вас читаю и тоже отвлекаюсь

bleyman

Он не сложнее, но в С традиционно используется постфиксный. А я — известный поборник традиционных ценностей!

VampiroAP

Проблема it++/++it волнует многие умы, на сайте Intel есть целая статья:
http://software.intel.com/ru-ru/blogs/2011/02/21/it-it/
В кратце: можно придумать случай, когда ++it в три раза быстрее it++ даже на современных компиляторах.

elenangel

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

fail. если программа делает что-то существенное по времени, процент времени потраченный в итераторах будет исчезающе мал. пусть программа работает пять минут и при этом тратит 1 секунду внутри итератора, вместо 0.3 секунд - это пренебрежимо мало, чтоб об этом задумываться.

Dasar

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

Maurog

В кратце: можно придумать случай, когда ++it в три раза быстрее it++ даже на современных компиляторах.
в дебуг версии :grin:

Werdna

в дебуг версии :grin:
в дебуг версиях компилят никогда не компилю.
все библиотеки должны использоваться только в продакшен-варианте, но точно с именами, на случай если упадёт.
Медленнее оно из-за ассёртов, но последние использовать — пидорство в чистом виде.

pitrik2

ещё так подумать постфиксный компилироваться дольше будет
компилятору надо будет тратить время на соображение можно ли в данном месте постфиксный соптимизировать
если в проекте много человек и этот код много раз компилируется и там много итераторов, и потом это время перевести на зарплатные деньги то может наверна нехило получится :)
:)

slonishka

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

zya369

а любое более сложное правило требует ... напряжения извилин.

для индустриальной разработки - недопустимо (c)

enochka1145

// Медленнее оно из-за ассёртов, но последние использовать — пидорство в чистом виде.
Учитывая, сколько нервов спасли на моих глазах assert-ы, я бы не стал такое говорить в общественных местах.
Конечно, почти всегда их надо дублировать if-ами.
Оставить комментарий
Имя или ник:
Комментарий: