Здравствуйте, sergii.p, Вы писали:
SP>1. Конструкции return std::move обычно вредны, потому как ломают RVO.
ээх плохо и давно про RVO читал, казалось наоборот ( пошел перечитывать )
SP>2. в функции rotate() цикл видимо должен начинаться так for (size_t j = i + 1 ... иначе не понятно кто с кем меняется. Вообще функция мутная, я что-то не разобрался, что она делает 
ага мутная ) тестов для нее еще не хватает , но в задачке проще было отладить через принт-дебаг ) а так она норм работает. поворачивает решетку Кардано для одноименного шифра ) в
SP>3. в функции merge неплохо бы сделать out.reserve(SQUARE_DIMENSION). Также это неплохо бы сделать в функции read_square() line.reserve(SQUARE_DIMENSION) потому как функция getline вычитывает из потока посимвольно
в общем случае для произвольного SQUARE_DIMENSION само собой. спасибо за напоминание, не подумал об этом. но для 4 и соответсвенно 16 символов в блоке, Small String Optimisation должны меня спасти ) там какраз, кажется 16 символов )
SP>в остальном мне код понравился
спасибо