пятница, 7 сентября 2018 г.

Перегрузка и частичная специализация функций

Возьмем следующий пример кода:
template <typename T> void foo(T); // строка 1
template <typename T> void foo(T*); // строка 2
template <>           void foo<int>(int*); // строка 3
Здесь в строке 1 мы объявляем шаблон функции с одним параметром T.
В строке 2 перегружаем нашу шаблонную функцию.
В строке 3 выполняем полную специализацию шаблонной функции, а именно ее перегруженного варианта в строке 2.

Теперь попробуем переставить строки 2 и 3 местами:
template <typename T> void foo(T); // строка 1
template <>           void foo<int*>(int*); // строка 2
template <typename T> void foo(T*); // строка 3
В обоих случаях будем вызывать нашу функцию так:
foo(new int);
Вопреки ожиданиям столь незначительное изменение меняет поведение программы.
Дело в том, что теперь специализация шаблонной функции в строке 2 относится к шаблонной функции в строке 1.

Далее в игру вступает та особенность компилятора, при которой он сначала выбирает наиболее подходящую перегрузку функции, а затем для данной перегрузки еще выбирает специализацию.
В первом фрагменте кода, компилятор сначала выбирает подходящую перегрузку функции, что для new int очевидно соответствует строке 2, а затем выбирает подходящую специализацию, и в итоге вызывается функция из строки 3:
template <>           void foo<int>(int*); // строка 3
Во втором фрагменте кода, компилятор всё также сначала выбирает перегрузку функции, это строка 3, потом смотрит, если ли специализации, но специализаций у данной функции нет. Во втором фрагменте кода специализация есть только у функции из строки 1, а у функции из строки 3 нет. В итоге вызывается функция из строки 3:
template <typename T> void foo(T*); // строка 3
По это причине не рекомендуется одновременно использовать перегрузки функций и их полную специализацию.

Куда сходить в Москве на выходных

Зеленым отметил, где уже был.
Желтым то, что хотелось бы посетить следующим.

суббота, 3 февраля 2018 г.

Способы вызвать крах программы в С++

Следующие способы вызвать крах программы в C++ взяты из книги Саттера.
  1. memset(0,1,1) - обращение по нулевому указателю
  2. abort()
  3. static_cast<char*>(0) = 0 - обращение по нулевому указателю
  4. static_cast<void(*)()>(0)() - вызов несуществующей функции по нулевому указателю
  5. throw std::logic_error()
  6. throw 0

воскресенье, 10 сентября 2017 г.

Загадка про охотника и ворону

На березе сидело четыре вороны. Пришел охотник и подстрелил одну. Сколько ворон осталось на березе?

четверг, 2 февраля 2017 г.

Книги для изучения C++

Начать изучение C++ рекомендуется с классической книги Б. Керниган, Д. Ритчи, "Язык программирования C". Понимание языка C, который лёг в основу C++, поможет вам лучше разобраться с особенностями C++. 

Дальше можно перейти к вводным курсам по С++.
  • Стенли Б. Липпман, Жози Лажойе, Барбара Э. Му "Язык программирования C++. Вводный курс".
  • Стивен Прата. "Язык программирования C++. Лекции и упражнения".
  • Герберт Шилдт. "Язык программирования C++. Вводный курс".
Кроме этого, для основательного понимания материала мы настоятельно советуем прочесть следующие книги по C++.
  • Скотт Майерс, "Эффективное использование С++".
  • Герб Саттер, Андрей Александреску, "Стандарты программирования на C++".
  • Герб Саттер, "Решение сложных задач на С++".
  • Герб Саттер, "Новые сложные задачи на C++".
Опытным слушателям могут показаться интересными следующие книги.
  • Андрея Александреску, "Современное проектирование на С++".
  • Бьерн Страуструп, "Дизайн и эволюция языка C++".

воскресенье, 28 февраля 2016 г.

Задача про визирей и жен

Было у султана N=12 визирей. Узнал он как-то, что у некоторых визирей неверные жены. Решил он им наказание устроить. Сделал так: каждого визиря с его женой посадили в полностью изолированные комнаты, и было им сказано, что сидеть им взаперти, пока все неверные жены не будут убиты своими супругами. Каждое утро все комнаты обходит слуга, проверяя выполнение этого условия. Как только выясняется, что все неверные жены мертвы, всех выпускают. На K=3-ий день всех выпустили, причем все верные жены остались живы. Как визири догадались? Уточнение. Все визири очень умны, и сплетней во дворце предостаточно, так что каждый визирь знает, верная или неверная жена у каждого другого визиря, но ничего не знает про свою. Никакого обмена информацией, пока они взаперти, нет.

четверг, 28 января 2016 г.

Паттерны Фаулера

После прочтения книги Мартина Фаулера Patterns of Enterprise Application Architecture у меня остались весьма двойственные впечатления. С одной стороны авторитет и опыт автора заставляет с уважением относиться к его произведению, тем более что в книги действительно можно найти не мало полезной информации по различным паттернам проектирования. Однако, многие паттерны уже давно встроены в стандартные библиотеки .Net framework и воспринимаются программистами как очевидная данность, в частности, паттерны для работы с данными. Кроме того некоторые вещи сейчас потеряли актуальность, например, паттерны, предлагающие варианты инкапсуляции создания объектов. Видимо, на момент написания книги подход Inversion of Control еще не был популярен.
Из паттернов Фаулера, которые мне понравились, и которые я хотел бы отметить, можно выделить следующие:

  1. Сценарий Транзакций vs модель предметной области
  2. Слой служб (Service Layer)
  3. MVC (Model View Controller)
  4. Интерфейс удаленного доступа (Remote Facade)
  5. Оптимистическая автономная блокировка (Optimistic Offline Lock)
  6. Пессимистическая автономная блокировка (Pessimistic Offline Lock)
  7. Блокировка с низкой степенью детализации (Coarse-Grained Lock)
  8. Неявная блокировка (Implicit Lock)