• Головоломка по ассоциативным контейнерам STL или Как решить одну задачу восемью очень разными способами
    0
    Ну зачем же так голословно теоретизировать. Ну не поленитесь замерить производительность. Вот мой код для тестов:

    Скрытый текст
    #include <iostream>
    #include <functional>
    #include <map>
    #include <chrono>
    
    template<typename T> class Compare
    {
    public:
    	enum Type { less, greater };
    	Compare() = delete;
    	Compare(Type type) : m_type(type) {};
    	bool operator()(const T &_Left, const T &_Right) const
    	{
    		if (m_type == less)
    			return (_Left < _Right);
    		else
    			return (_Left > _Right);
    	};
    private:
    	Type m_type;
    };
    
    inline bool less(int a, int b)
    {
    	return a < b;
    }
    
    inline bool greater(int a, int b)
    {
    	return a > b;
    }
    
    int main()
    {
    	/*auto mg = std::map<int, int, std::function<bool(int, int)>>(
    		std::greater<int>{}
    		);
    	auto ml =
    		std::map<int, int, std::function<bool(int, int)>>(
    			std::less<int>{}
    		);*/
    	
    	/*auto mg = std::map<int, int, Compare<int>>(
    		Compare<int>(Compare<int>::greater)
    		);
    
    	auto ml = std::map<int, int, Compare<int>>(
    		Compare<int>(Compare<int>::less)
    		);*/
    
    	auto mg = std::map<int, int, bool(&)(int, int)>(
    		greater
    		);
    
    	auto ml = std::map<int, int, bool(&)(int, int)>(
    		less
    		);
    
    	for (int i = 0; i < 100000; ++i)
    	{
    		mg.insert({ i, i });
    		ml.insert({ i, i });
    	}
    
    	const auto mm = { mg, ml };
    
    
    	auto start = std::chrono::system_clock::now();
    	int res = 0;
    	for (const auto & m : mm)
    	{
    		for (int i = 0; i < 100000000; ++i)
    		{
    			res += m.at(i % 100000);
    		}
    	}
    	std::cout << std::chrono::duration<double>(std::chrono::system_clock::now() - start).count();
    
    	std::cout << res << std::endl;
    }
    



    На моем компьютере на Visual Studio 2015 результаты такие:
    std::function — 24 сек
    указатель на функцию — 17 сек
    авторский Compare — 14 сек.

    На GCC 6.3.0 на coliru.stacked-crooked.com аналогичный результат (понятно, что там нельзя мерить производительность, но под рукой нет GCC):

    std::function — 29 сек
    указатель на функцию — 22 сек
    авторский Compare — 18 сек.

    Если не сложно, проверьте, пожалуйста, на своем компиляторе, интересно сравнить.

    Ничего против std::function не имею, сам люблю ее использовать, где это уместно, еще со времен буста.

    То, что std::function оптимизирована с помощью SBO, никто ж не спорит, это прописная истина еще со времен проживания в Boost. Не хватало, чтобы она еще кучу мусолила. И тем не менее, косвенного вызова функции через указатель в std::function не избежать, увы, во время компиляции не известно, что спрятано внутри нее.
  • Головоломка по ассоциативным контейнерам STL или Как решить одну задачу восемью очень разными способами
    0
    Код плюсую, но что-то в последнее время стало модно размахивать std::function, где уместно и где нет.
    Все-таки компаратор в больших (а лучше во всех) STL-коллекциях должен инлайниться. Полиморфный же std::function не инлайнится и ударит по производительности кода и оптимизациям компилятора. Компаратор — это критический по производительности участок кода. Здесь лучше оставить авторский Compare.
  • Визуализация всех денег и рынков мира
    0
    В том-то и вся соль. Сейчас долги кого-то перед вами учитываются в ваших балансах как активы.
    Вы взяли в одном банке 100 рублей и положили на депозит в другом (дали банку в долг), значит у вас есть 100 рублей как обязательство второго банка вам их вернуть.
    В итоге, первый банк уже рисует у себя на балансе проценты, которые вы будете платить за кредит, вы получаете справку от второго банка, что у вас есть вклад на 100 рублей, и вы уже не нищий. Для налоговой, например или для взыскания алиментов у вас есть актив, а не 0 (а про долги никто и не спрашивал).

    Если взаимно погасить, то у всех будет по нулям. А так, Петя, например, может продать Васин долг или заложить его Оксане, взяв у нее еще 75 рублей. Или может пиариться, что обладает активами в 100 рублей.
    Вот так крутится финансовая система. А если взаимно обнулить, то и ликвидность будет 0, и встанет все и сразу. Не далеки те времена, когда эта финансовая модель с треском грохнется.
  • Игнорируем лишние аргументы функции на C++
    +8
    Я пока не осилил всю статью, но с первого примера возник вопрос: а почему бы просто не использовать bind?

    const bool exists = WithObject (objectId,
            std::bind ([] { return true; }),
            std::bind ([] { return false; }));
    

    // вернет false
    // в MS VS 2012 в машинном коде в релизе нулевой оверхед: "push 0" - если результат передать аргументом другой функции
    std::bind([] { return false; })(0, 3.14, "foobar");
    
  • C++ User Group, встреча в Нижнем Новгороде
    0
    Прошу прощения, возможно, я что-то пропустил, но с февральской конференции в Москве видео так и не выложили (за исключением 2-х или 3-х докладов по-моему). В почту ничего пока не приходило.
  • Передача сохраненных аргументов в функцию
    0
    но передать ее потом куда-то не используя шаблонов затруднительно.
  • Передача сохраненных аргументов в функцию
    0
    // Какой должна быть сигнатура функции, принимающей такой аргумент?
    someOtherFunction(Lambda);
    

    void someOtherFunction(decltype(Lambda) lam);
    
  • Вычислите длину окружности
    +1
    Число Пи здесь указано недостаточно точно, но дело в том, что целочисленные константы в заголовочных файлах не требуют выделения памяти в отличие от остальных констант

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

    const int pi_i = 3;
    const int* n = &pi_i;
    
    или
    void foo(const int* n);
    foo(&pi_i);
    

    Компилятор может по возможности не выделять память под константу, а не обязан это делать всегда.
  • Сага о E_RPC_DISCONNECT
    0
    Следует дополнить, если кто-то вдруг не уловил:
    .NET-овский енумератор в данном случае — это обертка над COM-енумератором.
    foreach перед выполнением получает lib.Assets и запрашивает у него COM-енумератор через скрытый get__NewEnum и оборачивает в .NET-енуменатор, ссылка на саму коллекцию lib.Assets нигде в оригинальном коде не сохраняется. Енумератор живет до конца foreach, а ссылка на саму коллекцию пропадает сразу же перед входом в цикл. Если бы коллекция жила внутри lib, то все было бы ок, но, судя по всему (нужно убедиться в исходниках), проперти lib.Assets генерит новую коллекцию всякий раз, когда к нему обращаются.

    P.S. COM-енумератор — полноценный COM-объект.
  • Сага о E_RPC_DISCONNECT
    0
    Так очевидно же. Вы этой локальной переменной держите ссылку на коллекцию (то, что должен был делать правильно написанный енумератор) и не позволяете сборщику ее релизить раньше времени.
  • Сага о E_RPC_DISCONNECT
    +1
    Действительно, проблема в COM. Я несколько лет разрабатывал COM-серверы на C++. Всякий разработчик COM знает, что енумератор, запрашиваемый у COM-коллекции через get__NewEnum, пока жив сам, должен держать ссылку на итерируемую коллекцию с поднятым счетчиком (за исключением копирующих енумераторов, которые копируют элементы коллекции в себя). В майкрософтовском ATL, на базе которого часто реализуются COM и коллекции в том числе, это сделано автоматом:
    … holds a COM reference on the collection object to ensure that the collection remains alive while there are outstanding enumerators

    Судя по симптомам, в Вашем COM-сервере об этом скорее всего забыли. Без исходников на 100% гарантировать конечно нельзя.

    точно такая же работа без GetEnumerator() то есть по индексу — к дисконнекту не приводит

    Как раз, потому что в этом варианте не участвует кривонаписанный COM-енумератор.
    var asset = lib.Assets[i]; получаем коллекцию и напрямую (без промежуточного енумератора) из нее берем элемент.

    Кстати, в COM можно реализовать проперти так, что Assets возвращает коллекцию, а Assets(i) сразу нужный элемент без создания и заполнения коллекции. Не знаю, поддерживает ли такое клиент на C#. Но это уже другая песня.
  • Указатели, ссылки и массивы в C и C++: точки над i
    0
    Действительно, в разделе 5.7 (4). Замечательно. В таком случае, у автора все в порядке с выходом за пределы. В выражении &x + 1 нет UB.
  • Указатели, ссылки и массивы в C и C++: точки над i
    0
    Спасибо. Для меня это оказалось откровением. Действительно, стандарт позволяет при адресной арифметике выходить за пределы массива только на 1 элемент (но не разыменовывать!). Далее одного элемента — UB.
    Век живи — век учись.
    А как насчет такой конструкции, будет ли это считаться UB?
    int x;
    std::accumulate(&x, &x + 1);
    

    Скорее всего, да. Про адресную арифметику с переполнением я в стандарте нашел сноску только насчет массивов. Но можно ли указатель на единичную переменную трактовать как массив из одного элемента?
  • Указатели, ссылки и массивы в C и C++: точки над i
    +3
    Еще более плохая практика. Вероятность нарваться на границу защищенного сегмента памяти — просто.

    Здесь у автора все в порядке. Ссылаться за пределы массива можно и даже нужно. Итераторы конца последовательности (end) этим и занимаются. Разыменовывать нельзя, да, а указывать — на здоровье.
  • Указатели, ссылки и массивы в C и C++: точки над i
    0
    int (*x)[7] объявляет указатель. Его размер на стеке равен размеру указателя для данной платформы и не зависит от того, на что он указывает.
    sizeof(int (*)[7] ) == sizeof(int (*)[1000] )== sizeof(int*)
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    0
    Допустим, я компилирую PE / elf модуль под другую ОС (кто сказал, что PE только для MS?), где адрес 0 — корректный.

    Вы же указываете компилятору целевую ОС. Ну вот, компилятор знает, что в целевой ОС адрес 0 корректный, значит для null-представления он выберет что-то более подходящее.
    Случай действительно синтетический. Если бы возникала такая потребность, то компиляторы реализовали бы опции переопределения null-значения.
    Это мои размышления, я не претендую на истину :)
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    0
    А Вам переопределять и не нужно. Ваш компилятор знает, под какую архитектуру + ОС он компилирует, отсюда, ему виднее, какие адреса можно использовать как заведомо невалидные. Например, в Windows в подсистеме виртуальной памяти хоть для x86, хоть для IA-64 по нулевому адресу гарантированно нельзя разместить объект. Компилятор это знает и использует в этом случае 0 для физического представления null указателя.
    Повторюсь еще раз насчет макроса NULL. В C++ NULL можно определить только константным целочисленным нулем. Попробуйте сделать редефайн #define NULL 1. В строчке кода int* p = NULL получите ошибку компиляции. Не кастуются в C++ целые числа к указателям, исключение только для константного нуля интегрального типа. Это правила языка. Кстати, Страуструп против использования макроса NULL в C++, говорит, выбросите его и используйте 0 (хотя, для меня NULL удобнее).
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    0
    Ага, значит, мы можем переопределить null на конец памяти?

    Если Вы о макросе NULL, то его переопределение вряд ли чем-то поможет, а скорее навредит. Подозреваю, что везде он будет определен как ноль, с различными вариациями типов 0, ((void*)0), ((int)0).
    Само же особое состояние null указателя переопределить никто не может, оно задается компилятором. Мы лишь можем присвоить это состояние через p = 0 или p = NULL и сравнить с тем же 0 или NULL.
    Тут путаница с самим словом NULL. В том же Паскале используется nil, оно чуть-чуть более нейтрально.

    Как раз NULL и был призван решить эту путаницу, чтобы «0» не маячил перед глазами и не давал ложного ощущения, что p=0 — это присваивание адреса нулевой ячейки, p = NULL уже яснее. NULL не значит zero, NULL значит пустой, как в SQL.
    Кстати, я смотрю дискуссия разделилась на независимые ветки, и нашу ветку не читают :), товарищи в других ветках продолжают наезжать на стандарт, за то, что он якобы не позволяет размещать данные в нулевой ячейке, вот наглядный пример интерпретации, якобы p = 0 обязательно настраивает указатель на нулевую ячейку памяти.
    А почему не значения null, которое могло бы быть переопределено?

    Этого я не знаю. Предположу, что по тем же причинам, что и отсутствие типа bool в C. Для нового значения null, нужно было вводить новый тип данных. Наверное, встроенные типы языка C должны были соответствовать типам платформы. В C++ же добавили nullptr с типом nullptr_t. Опять же, переопределить его никто не даст, также никто не обязан знать его физическое представление.

    Подытожу:
    1. #define NULL лишь для удобства чтения, на нем нет смысла зацикливаться, его переопределение ничего хорошего не даст, уверен, что на всех платформах он определен как 0 (с типом void* или без него или еще с каким-либо типом, но все равно 0).
    2. Каждая платформа имеет свой зарезервированный пустой указатель. О его реальном физическом представлении знает лишь компилятор.
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    0
    По стандарту нулевой адрес может быть вполне корректным. Язык C (а также C++) вводят понятие null указателя. Это указатель с определенным зарезервированным значением, которое сигнализирует, что указатель не указывает никуда. Это значение не обязано представляться физическим нулем, может быть, что угодно, например, 0xffffffff. Но, т.к. это представление сильно зависит от платформы, устанавливать значение указателя в особое состояние null необходимо присваиванием нулевого значения целого интегрального типа. То есть int* p = 0; инициализирует разрядную сетку указателя значением 0xffffffff, и при этом p == 0 — истина, if (p) будет ложно.
    И это не только в теории. Есть системы, где null указатель не представлен физическим нулем: c-faq.com/null/machexamp.html
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    +4
    Возможно, я не прав, тогда пусть меня поправят.
    Я предлагаю вот таким способом разрешить спор. Если я правильно понял стандарт, я могу написать свой компилятор, который, следуя букве стандарта, имеет полное право на каждый оператор p->x (в том числе &p->x) «трогать память» под переменной x (считывать в регистр, в отладочных целях, например). Вопрос эффективности не волнует, зачем это делать — тоже не важно. Ведь задача стандарта — быть максимально абстрагированным и не делать предположений о реализации.
    В таком случае мой компилятор будет соответствовать стандарту, а ((T*)nullptr)->x будет стабильно падать. Также на моем компиляторе будет стабильно падать пример из комментария выше. Следовательно, оба примера являются UB.
    Осталось доказать, что мой компилятор соответствует стандарту, и я ничего не упустил.
  • Разыменовывание нулевого указателя приводит к неопределённому поведению
    0
    Отличие от nullptr тут одно. С nullptr — это гарантированное UB на уровне языка в данной конкретной строке кода, независимо от поведения других частей программы. А с fake_ptr UB, если разработчик заведомо знает, что под fake_ptr реально не размещен объект (то есть, нужно знать как работает вся программа и даже оборудование, вдруг оно размещает по данному адресу объект).
  • Аннотация к «Effective Modern C++» Скотта Майерса. Часть 2
    +2
    Здесь в статье или в оригинале ошибка:

    template<typename T> void setName(T&& _name) {
        name=std::forward<std::string>(_name);
    }
    

    std::forward<std::string>(_name) всегда вернет rvalue ссылку std::string&&, независимо от типа ссылки _name. То есть, будет работать как std::move.
    Правильно std::forward<T>(_name)
  • Городские легенды о медленных вызовах виртуальных функций
    0
    Оказывается, ниже уже ответили, не дочитал. Извиняюсь.
  • Городские легенды о медленных вызовах виртуальных функций
    +1
    Если точно уверен, что base_ptr указывает именно на concrete_type, то
    static_cast<concrete_type*>(base_ptr)->concrete_type::function(args...)
  • Именованные параметры C++. Не пригодились
    +16
    Для плюсов:
    std::tie(x, y) = getPosition();
  • Методы расширения в С++
    +3
    Вот поэтому я и уточнил, что:
    просматиривать глазами

    А код часто приходится читать глазами в текстовых редакторах, в репозиториях… Читаемый интерфейс класса — это важно.
  • Методы расширения в С++
    0
    Мультиметоды успешно реализуются уже на текущем синтаксисе, даже на C++03: habrahabr.ru/post/155515/
  • Методы расширения в С++
    +4
    Полезным с точки зрения инкапсуляции будет, как с перегрузкой операторов. Страуструп рекомендует объявлять операторы внешней функцией, если им не требуются закрытые члены. Таким образом, при проверке инвариантов и рефакторинге внутренностей мы просматриваем только операторы-члены.
    Проблемы те же: интерфейс класса распадается на на члены и свободные функции, просматиривать глазами такой интерфейс неудобно, а порой и невозможно твердо понять в куче заголовочников, может ли еще где-то быть определен метод.
  • Comment from a drafted post.
  • Comment from a drafted post.
  • Comment from a drafted post.
  • Comment from a drafted post.
  • Мьютексы в стиле Rust для C++
    +2
    Спасибо за статью!

    Пару вопросов:
    1) А почему бы не использовать recursive_mutex? Или лучше задать тип мьютекса дополнительным параметром шаблона. Тогда можно и разрешить копировать Accessor, и множественно вызывать SharedResource::lock().
    2) Поддержка const SharedResource намеренно отсутствует? Можно реализовать, сделав m_mutex mutable и добавив класс ConstAccessor, который будет возвращаться из SharedResource::lock() const.
  • Инстанциирование шаблонов функций по списку типов (Часть 1)
    0
    так как позволяет писать
    typedef TypeList<int,char,bool,string, EmptyList> MyTypeList;
    вместо классической записи
    typedef TypeList<int,TypeList<char,TypeList<bool,TypeList<string, EmptyList>>>> MyTypeList;

    Мне не приходилось пользоваться Loki (предпочитаю boost::mpl), но, тем не менее, я заглядывал в исходники из любопытства. Там есть мейкеры для TypeList:
    typedef MakeTypelist<int,char,bool,string>::Result MyTypeList;

    Также на макросах:
    typedef LOKI_TYPELIST_4(int,char,bool,string) MyTypeList;
  • Крестики-нолики: компилятор против человека — экстремальный метапрограмминг
    0
    Именно такой подход сразу и пришел мне в голову: через mpl::equal выражать. Это менее красиво, в разы тормознее, но формально правильно по спецификации mpl, ничего тут не поделаешь.

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

    Я о том же выше и написал, что неспецифицировано. Например, для операции mpl::erase гарантируется лишь, что результат будет «concept-identical» источнику. То есть, с сохранением набора концепций, но фиг знает каким классом.
    A sequence s1 is said to be concept-identical to a sequence s2 if s1 and s2 model the exact same set of concepts.

    На практике из mpl::vector[N] будет получаться mpl::vectorN-1, я бы мог забить вторую спецификацию mpl::vector1<int> и, уверен, 100 лет бы проработало, но формально — это ошибка.

    принимать конкретно ваши (fas::) списки типов

    К сожалению, fas — не моя, это laphroaig :)
    Ни сколько не умаляю достоинств mpl. Сам пользуюсь. Ее возможности более широкие. Широченные. А за высокий уровень абстрагирования приходится платить временем компиляции.
  • Крестики-нолики: компилятор против человека — экстремальный метапрограмминг
    0
    Да, помню, как я раздосадовался, когда хотел красиво специализацией раздиспатчить что-то типа:

    template <typename V>
    class C{};
    
    template <>
    class C<mpl::vector<int> >{};
    


    Не специфицировано, что может получиться после манимуляций с вектором (получится, конечно, тот же вектор как концепт, но имя у него может быть vector0, vector1 и т.д.). По факту у меня мог прийти mpl::vector1<int> или mpl::vector<int>

    Пришлось извращаться менее красиво.
  • Крестики-нолики: компилятор против человека — экстремальный метапрограмминг
    0
    Кроме того boost::mpl работает с векторами, а faslib со списками

    Ну почему же? MPL тоже работает со списками и с другими классами и концепциями последовательностей, а также итераторов.

    А получилось здорово, конечно.
  • Роскомнадзор посоветовал размещать сайты на отечественных хостинг-площадках
    0
    Нашему бизнесу не только пофиг. Он еще посодействовать не прочь. На примере Яндекса и LiveJournal, случайно наткнулся на этой неделе: www.e-xecutive.ru/blog/Easy_Eco/15385.php
    Сам пробовал, действительно Яндекс именно ту статью про Барака не находит (хотя опубликована она на нескольких сайтах), даже если указать ему на каком сайте искать и вбивать в запрос заголовок, теги, все равно не находит. Судить не берусь, может, на это какие-то другие причины есть, не пытался исследовать, может баг. Google прекрасно выводит первыми ссылками на странице.
  • Objective-c блоки и c++ лямбды
    0
    Полностью согласен. Можно улучшать, можно придумать еще кучу способов. Главное, что способ с std::function не единственный и далеко не самый эффективный.
    А все от того, что бытует мнение, что лямбды — объекты неизвестного типа. С decltype тип вполне известен.
    Стараюсь не оборачивать лишний раз лямбды в std::function из-за лишнего оверхеда, особенно, когда лямбда не влезает в small buffer optimization.
  • Objective-c блоки и c++ лямбды
    0
    Единственным способом переместить лямбду на heap является приведение ее к типу std::function

    Способ №2:
    auto lamb = []() {return 5;};
    auto* p = new decltype(lamb)(lamb);
    


    Способ №3:
    template <typename T>
    T* heap_alloc(T const& value)
    {
        return new T(value);
    }
    
    auto* p = heap_alloc([]() {return 5;});
    


    Способ №4:
    std::vector<decltype(lamb)> v;
    v.push_back(lamb);
    

    И т. д…