LINUX.ORG.RU

Как в C++11 принято разделять реализацию и объявление шаблонных классов

 ,


0

5

В общем есть класс шаблонный у которого есть шаблонные методы, как можно реализовать разделение на .h и .cpp без вот таких вот костылей в cpp'шнике?

template class DataField<long>;
template class VariantsDataField<long>;
template VariantsDataField<long> VariantsDataField<long>::operator *<long>(VariantsDataField<long>);
template VariantsDataField<long> VariantsDataField<long>::operator /<long>(VariantsDataField<long>);
?

★★★★★

Инклудишь .cpp в .h и всё)

Dikar ★★
()
Ответ на: комментарий от nanoolinux

Отвалившийся процесс в эрланге - это так же как и эксепшн.

О, да, конечно.

Рассказываю историю из недавних.

Вдруг, после очередного обновления, отвалился некий сервис, назовём его A. Причём отвалился насовсем. Отладочные логи показали, что сервис отваливается всегда, через пару минут после запуска системы, в непредсказуемом месте. То есть, не «строка 666 содержит ошибку, сервис падает», а просто где попало. Самое интересное, что код A с предыдущего релиза не меняли вообще.

Оказалось, в конце концов, вот что. Сервис A висел под супервизором. Под этим же супервизором висел другой сервис B. Этот сервис был реализован как gen_server - вот только одна из handle_* функций в нём возвращала не то. Вместо {noreply, Something} возвращала {ok, Something}.

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

Что-то мы там наоптимизировали. Сервис B стал работать в разы быстрее. И падать чаще. Соответственно, увидев, что сервис падает уж очень часто, супервизор сказал «всё, ребята, я задолбался», убил всех своих детей (в том числе сервис A, ни в чём не повинный) и убился сам. Всё.

В языке со статической типизацией оно бы не скомпилировалось вообще. И мы увидели бы ошибку на полгода раньше.

И только не говори мне, что с эксепшенами бывает так же или даже хуже. Теоретически - может быть, но на практике - не верю.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Ты тоже что ли на ырланге пишешь? Мои соболезнования.

Самое отвратительное в динамике — это даже не баги, а сам процесс девелопмента. Чтобы понять, что тебе прилетит в функцию, надо лезть в чужую подсистему, в код, авторы которого пять лет назад сторчались и померли от спида, и потом держать это в памяти на будущее. Омерзительно.

anonymous
()
Ответ на: комментарий от anonymous

Спасибо. Ничего, это не надолго.

Чтобы понять, что тебе прилетит в функцию, надо лезть в чужую подсистему, в код, авторы которого пять лет назад сторчались и померли от спида, и потом держать это в памяти на будущее. Омерзительно.

Угу. У нас на все функции есть -spec, вот только никто, в том числе диалайзер, не гарантирует, что туда не прилетит какая-нибудь лажа.

Miguel ★★★★★
()
Ответ на: комментарий от NegatiV

Неужели тесты отрабатывали правильно?

Угу. Всё ведь работало. Сервис B завершал цикл - и, вместо того, чтобы перейти на его начало, падал. И поднимался супервизором. Всё почти так же, как при нормальном функционировании.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Что-то подобное и у нас случалось: переполнялся почтовый ящик у процесса и сервер отваливался. Из-за ошибки в match pattern. :)

NegatiV
()
Ответ на: комментарий от deterok

Ты вообще не понимаешь, что такое шаблоны, да?

anonymous
()
Ответ на: комментарий от Miguel

Ваще-то в Лиспе макросы таки компилируются (так как внутри те же функции). В c++ можно было бы сделать так же, ценой раздутых кодом макросов бинарников и ценой невозможности кросс-компиляции.

anonymous
()
Ответ на: комментарий от anonymous

Ваще-то в Лиспе макросы таки компилируются (так как внутри те же функции).

Да, поскольку скомпилированная функция может быть исполнена в компайл-тайме. Согласен.

То же самое относится к TH.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

В языке со статической типизацией оно бы не скомпилировалось вообще.

Статическая типизация тут бы никак не помогла.

В плюсах ты бы из функции возвращал какую-нибудь перемунную типа

enum class result { ok, noreply }

И тебе бы ничто там не мешало точно так же вместо result::noreply написать result::ok.

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

А что мешало протестировать сервис без перезапусков или сделать проверку возвращаемого значения?

Ну и то что в логи никто не смотрел говорит скорее о том, что у вас там изъяны в методике разработки, а не неудачно подобранный инструмент.

И мы увидели бы ошибку на полгода раньше.

А, возможно, что и нет. Т.к. на плюсах писали бы программу на полгода дольше.

anatoly
()
Ответ на: комментарий от anatoly

Статическая типизация тут бы никак не помогла.

Товарищ, вы в уме?

И тебе бы ничто там не мешало точно так же вместо result::noreply написать result::ok.

Нет. Потому что там НЕТ варианта ok. Там есть reply, noreply и stop. И падало оно ИМЕННО потому, что возвращался неподходящий по типу результат.

А что мешало протестировать сервис без перезапусков или сделать проверку возвращаемого значения?

Сервис включён в экосистему, в отрыве от неё он не работает.

А проверка возвращаемого значения уже есть, в gen_server. Она-то и крашила сервис, возвращавший не то.

Т.к. на плюсах писали бы программу на полгода дольше.

Речь шла не о плюсах vs эрланг, а о статической типизации vs типизация эрланга. Языков со статической типизацией много.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Товарищ, вы в уме?

А вы доктор и хотите пригласить на консультацию?

Нет. Потому что там НЕТ варианта ok. Там есть reply, noreply и stop. И падало оно ИМЕННО потому, что возвращался неподходящий по типу результат.

Ок. Был не прав.

anatoly
()
Ответ на: комментарий от Miguel

Но, опять же, цена этой радости - невозможность кросс-компиляции, или необходимость параллельно компилировать под две платформы.

anonymous
()
Ответ на: комментарий от wakuwaku

Подскажи сам, пожалуйста, какую метку для тебя добавить.

«динамические опердени» ему подойдет.

Pavval ★★★★★
()
Ответ на: комментарий от Miguel

Но у меня тоже историй есть.

Есть либа, внутрях написана на сплюсе, но интерфейс к ней - на С. К этой самой либе есть прослойка, в виде сплюсового хидера и спп файла, который, как выяснилось позже, реализует точно такой же интерфейс, как и внутренние классы либы. Спп файл прослойки делает загрузку либы dlopen’ом, а потом dlsym’ом вытаскивает указатели на ф-ии и вызывает их потом в методах.

И вот, значит, компилишь ты этот хидер с спп файликом в проект, запускаешь значит конструктор любого из классов из хидера и всё падает. Так, чего там на дебагер показывает? Ух ты! Конструктор вызывает ф-ию, которая вызывает конструктор, которая вызывает ф-ию, которая вызывает конструктор … и так пока не стековерфлоу. И все это лишь из-за совпадения названий классов внутри либы и в хидере. Названий грёбаных классов! Названий Грёбаный Классов!

Я на это потратил неделю копания с дебагером в нутрях либы, которую не писал. Потом засунул все классы в хидере в неймспейс и всё заработало.

И вот теперь скажи мне, как мне в этом случае помогла бы статическая типизация? Если какие-то чумовые ребята наваяли всё на указателях на воиды (производительность, кококо!) как тебе поможет статическая типизация? Ну и где Pavval, который кричал про то, что есть хорошие и годные библиотеки на все случаи жизни?

Я не спорю, твой случай - наглядный пример нужности статической типизации, потому-что в одном конкретно взятом случае она бы помогла, но пойми - я ругаю спп за то, что эту идею сплюсмены извратили до невозможности. Они кричат про высокоуровневый универсальный язык, но при этом прячут голову в песок, когда им говорят о тормозутости шаред петеров. Они тут же отвечают „мы умеем указатели“ и начинают творить падучее и неюзабельное гуано, которому никакая статическая типизация не поможет - только костёр. Они говорят, что всё написано на сплюсе - игры там, броузеры. Но что такое современные игры? Что такое современные броузеры? Где же обещанная „производительность“?

Можно ещё сказать вот что. Вот допустим определил я enum {reply, norelpy, stop}. Как мне это экспортировать из либы? Как вообще экспортировать классы и типы? Никак. Нужны костыли в виде пимплов или пихать шаблоны в хидера и распространять с исходниками аля буст. И это значит универсальность? Гибкость?

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Ну и где Pavval, который кричал про то, что есть хорошие и годные библиотеки на все случаи жизни?

Я тут, солнышко:) А еще есть и плохие и негодные либы на все случаи жизни.

Pavval ★★★★★
()
Ответ на: комментарий от Pavval

В духе „я пишу хелоуворд

int main()
{
 char *s;
 memcpy(s, "hello world\n", 12);
 printf(s);
 return 0;
}
но программа падает почему-то. Подскажите решение.“? Адекватный пример?)

nanoolinux ★★★★
()
Ответ на: комментарий от anatoly

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

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Если какие-то чумовые ребята наваяли всё на указателях на воиды (производительность, кококо!) как тебе поможет статическая типизация?

Ну, очевидно, она поможет тем, что не будет позволять делать «указатели на войды».

Статическая типизация в варианте C++, к сожалению, очень слаба, и от таких вещей не защищает. Это означает ровно одно: нужна более сильная статическая типизация.

Впрочем, твоя история вызывает известные сомнения. Если у либы сишный интерфейс, то что там внутрях — по идее, не должно влиять никак.

Другой вопрос, если ты подключил либу исходниками. Тогда да, проблемы понятные — но не надо тогда говорить про интерфейс на C.

но пойми - я ругаю спп за то, что эту идею сплюсмены извратили до невозможности

Вообще-то, ты не ругал плюсы, а восхвалял эрланг. См. Как в C++11 принято разделять реализацию и объявление шаблонных классов (комментарий) — если бы ты там ругал плюсы, я бы тебя только поддержал, плюсы полное говно; но ты явно считаешь, что падение эрланговского процесса — это так, ничего особенного. Я на это и отреагировал.

Miguel ★★★★★
()
Ответ на: комментарий от nanoolinux

Не менее интересно, как сильно будет тормозить Крайзис, если его написать на Эрланге.

anatoly
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.