27 декабря 2010 г.

Нововведения в C++0x, которые не могут не радовать (меня)

Просмотрел повнимательнее список новшеств в будущем стандарте C++0x и обнаружил, что многие грабли, которые приходилось раньше реализовывать самостоятельно или городить воркэраунды, теперь будут поддерживаться конструкциями языка или добавлены в стандартную библиотеку. Это не может не радовать, потому что это сильно облегчает жизнь.

  1. Первым пунктом у меня идут потоки и объекты синхронизации (§30 [thread]): thread, mutex, lock, condition_variable, future, ... Наконец-то! Надеюсь, теперь можно будет выкинуть весь самописный код, который реализовывал классы с подобной функциональностью для использования на различных платформах. Конечно, было бы неплохо расширить список поддерживаемых Стандартом объектов синхронизации, но и существующий список вполне хорош.
  2. static_assert — проверка условий на этапе компиляции, которой так не хватало в предыдущих версиях Стандарта. Очень полезна для проверки размеров типов данных и кратности этих типов каким-то заданным значениям. (§7 [dcl.dcl])
  3. Списки инициализации и универсальная инициализация — новая синтаксическая конструкция (§8.5.4 [dcl.init.list]), которая позволяет инициализировать массивы, структуры данных и контейнеры следующим образом:
    double ad[] = { 1, 2.0 };
    S2 s22 { 1.0, 2, 3 };
    std::map<std::string, int> anim =
      { {"bear",4}, {"cassowary",2}, {"tiger",7} };

  4. shared_ptr — умные указатели (§20.9.11 [util.smartptr]). Объект, хранимый умным указателем, уничтожается только после того, как счетчик ссылок на объект будет равен нулю.
  5. Лямбда-выражения (§5.1.2 [expr.prim.lambda]). К самим по себе лямбда-выражениям я отношусь достаточно спокойно. Даже, пожалуй, скептически, потому что мне кажется, что фанатичное использование лямбда-выражений приведёт к хаосу (особенно выражений, которые изменяют состояние классов). Но у лямбда-выражений есть свойство, которого мне раньше не хватало — их можно передавать в классы и алгоритмы стандартной библиотеки (и в пользовательские шаблоны) в качестве предикатов. Раньше надо было городить кучу кода, определяя дополнительные функции и классы, причем передавать в шаблон локальный класс запрещено. А с новым стандартом можно сделать так:
    std::sort(x, x + N,
              [](float a, float b)
              { return std::abs(a) < std::abs(b); });

  6. Автоматический тип данных auto — тип объявляемой переменной определяется самостоятельно из типа инициализатора. Особенно удобно использовать при работе с итераторами контейнеров и другими типами, от которых зависит шаблон, чтобы не париться с горой typedef'ов. (§7.1.6.4 [dcl.spec.auto])
  7. Возможность вызова конструкторов класса из других конструкторов этого же класса (§12.6.2 [class.base.init]). Очень сильно облегчает написание конструкторов классов, помогает избежать дублирования кода инициализации.
  8. Цикл for по коллекциям (§6.5.4 [stmt.ranged]). Не очень актуально, учитывая появление auto и лямбда-выражений, но объём кода уменьшает.
    int array[5] = { 1, 2, 3, 4, 5 };
    for (int& x : array)
      x *= 2;

  9. Из маленьких приятных мелочей можно упомянуть поддержку генераторов случайных чисел (§26.5 [rand]), атомарных операций (§29 [atomics]), регулярных выражений (§28 [re]) и новых алгоритмов. Например, алгоритм iota (§27.6.5 [numeric.iota]), который заполняет заданный интервал инкрементирующимися значениями, начиная с заданного (подобный функционал я реализовывал с помощью алгоритма generate и самописного класса UniqueNumberGenerator).

15 декабря 2010 г.

Подключение сетевого диска через SSH в Ubuntu

Описание подключения сетевого диска обычным способом см. "Подключение сетевого диска в Ubuntu".

Если доступ на удалённый сервер открыт по протоколу SSH, то в Ubuntu используя модуль sshfs можно подключить любую доступную директорию этого сервера как локальную. Для подключения/отключения директории с помощью sshfs права суперпользователя не нужны.

Установка sshfs:

sudo apt-get install sshfs


Подключение директории удалённого сервера. Например, директорию /some_dir/common с сервера 192.168.1.25. Также предположим, что текущее имя пользователя на локальном компьютере совпадает с именем пользователя удалённого сервера (при подключении будет запрошен пароль доступа через SSH). Следующая команда монтирует директорию /some_dir/common с сервера 192.168.1.25 в локальную директорию ./remote_dir:

mkdir ./remote_dir
sshfs 192.168.1.25:/some_dir/common ./remote_dir


Если имя пользователя на удаленном сервере отличается от локального, то нужно указать это имя при подключении. Например, имя пользователя на удалённом сервере user0001 (при подключении будет запрошен пароль доступа через SSH для пользователя user0001):

sshfs user0001@192.168.1.25:/some_dir/common ./remote_dir


Отключение директории:

fusermount -u ./remote_dir

Команда sshfs также принимает различные опции для управления правами доступа, идентификаторами пользователя и т. д.

Об автоматизации подключения можно почитать здесь.

10 декабря 2010 г.

Цитата: Грэм

Баян, конечно, но странно, что баян не теряет актуальность.

Если вы поедете в Кремниевую Долину, то вы увидите лишь здания. Но Долина состоит не из зданий, а из людей. (...)

Из офисных комплексов для высокотехнологичных компаний не получится Кремниевой Долины, потому что ключевой момент в жизни стартапов наступает еще до того, как им потребуются офисы. Ключевой момент — это когда три парня начинают работать вне своего дома. Там, где стартап получит финансирование, он и останется. (...) Так что если вы хотите, чтобы у вас была новая Кремниевая Долина, то у вас должны быть два или три парня, которые сидя за кухонным столом решают основать стартап. И для этого вам потребуются такие люди.

Наши клоуны начали со зданий.

9 декабря 2010 г.

Саттер рапортует

Херб Саттер рассказал о том, что наконец-то разум восторжествовал комитет C++ решил избавиться от уродливых конструкций атрибутов с двойными квадратными скобками и заменил их на ключевые слова. Лично мне новый вариант нравится намного больше.

Было:
class [[base_check]] Derived : public Base {
public:
  virtual void f [[override]] ();
  virtual double g [[final]] ( int );
  virtual void h [[hiding]] ();
};

Стало:
class Derived explicit : public Base {
public:
  virtual void f () override;
  virtual double g( int ) final;
  virtual void h() new;
};

STL: есть ли жизнь без исключений

Известно, что при компиляции кода можно отключить обработку исключений компилятором (например, опцией -fno-exceptions в GCC, или /EHs- в Visual Studio). Однако, отключение обработки исключений вовсе не означает, что программа не будет генерировать исключения. Это всего лишь означает, что компилятор не будет создавать код для обработки исключений и уничтожения автоматических объектов. А исключения будут продолжать генерироваться — операторами new при нехватке памяти, методом at() класса std::vector при выходе за пределы массива, просто операторами throw расставленными программистом по своему коду и т. д. Различие лишь в том, что так как в программе не будет вообще никакого кода, перехватывающего исключения, то любое сгенерированное в программе исключение приведет к вызову terminate().

Классы стандартной библиотеки сообщают об ошибках только с помощью исключений и никак иначе. Проблема использования STL в том, что когда мы отключаем поддержку исключений в проекте, то лишаемся механизма обработки ошибок. И если проблему с оператором new можно решить его заменой на new (nothrow), то исключение, генерируемое в аллокаторе при вызове vector::resize(), вроде как ничем не заменишь.

6 декабря 2010 г.

Clang API: обход AST (clang-2.8)

В прошлом посте про Clang мы получали абстрактное синтаксическое дерево в виде XML. Теперь попробуем выполнить обход AST вручную. Вручную — это значит создать и инициализировать в программе экземпляры классов, необходимых для анализа исходного файла, построить дерево и получить в коде программы доступ к каждому узлу по очереди, чтобы сотворить с узлами какое-нибудь действо.