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>);
?

★★★★★

По-моему компиляторы еще не научились этому. Я разделяю декларацию и реализацию, но оставляю все в заголовочном файле.

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

Нет, ну реально никак?
А как быть допустим, если я хочу либу сделать и при этом не хочу вот так писать?
Допустим я все в заголовочник помещу, но не хочу все показывать посторонним людям. Можно ли сделать вариант заголовочника для остальных(без кода) или не прокатит? Что-то у меня уже от этой магии все перемешалось.

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

Нет, ну реально никак?

Реально. Было для этого ключевое слово export, которое гордо поддерживал только один компилятор. И в С++11 оно уже убрано (именно потому, что никто не хотел реализовывать по техническим причинам).

А как быть допустим, если я хочу либу сделать и при этом не хочу вот так писать?

Объединяйся с хотящими секса без обязательств и подобными.

Допустим я все в заголовочник помещу, но не хочу все показывать посторонним людям.

Если есть, что выделить в типонезависимый базовый класс (не шаблонный) - выделяй и прячь. Иначе никак.

Можно ли сделать вариант заголовочника для остальных(без кода) или не прокатит?

Нет. Как они тогда инстанциируют код, которого у них нет?

Pavval ★★★★★
()
Последнее исправление: Pavval (всего исправлений: 1)
Ответ на: комментарий от deterok

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

staseg ★★★★★
()

Ладно, спасибо всем за помощь.

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

Решения нет. Привыкай, таков спп. Он будет тебе мешать всегда и всюду. Что бы ты не придумал, спп всегда будет иметь ограничения, которые заставят тебя либо использовать костыли, либо переделать всё, что ты придумал. Со временем, когда ты наберёшься опыта, эти проблемы может быть и исчезнут, но до этого пройдёт лет пять. Но даже тогда ты будешь спотыкаться на каких-то эфемерных хренотенях, о которых знают даже не все члены комитета. Спп - это ад.

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

Я еще и питоньщик :)

Ушел от ++ года 2 назад, сейчас вот один проектик взял.

deterok ★★★★★
() автор топика

AFAIK, помещение шаблона целиком в *.h является общепринятой практикой. По крайней мере, тот же Boost так и делает. И у Майерса тоже есть советы делать именно так, емнип в «Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ».

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

Что? В эрланге нет такой проблемы вообще, ты что-то путаешь. Там весь код по сути типонезависим. Вот тебе пример работающий и с целыми и вещественными числами:

f(X) ->
  X*X;
А вот это что-то в духе, ммм..., даже не знаю... в сплюс-сплюсе такое есть вообще? Откомпелированые шаблончики в объектниках не сохранить, да)
f({my_type, Data}) ->
  Data ! please_double,
  receive Any -> Any end;
f(X) -> X*X.

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

Вот тебе пример работающий и с целыми и вещественными числами:

И падающий в рантайме при попытке применить эту функцию к чему-то ещё. В крестах хоть какая-то типизация есть, и уже поэтому эрланг у них отсасывает.

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

И падающий в рантайме

Я ждал, что ты это напишешь. И вот слушай сюда, я отвечаю тебе на подобные дебильные вопросы один раз.

Если ты пишешь, что-то, что должно принимать только числа, то в эрланге ты просто пишешь эту ф-ию и всё. Если тебе нужна защита от дурака, ты пишешь:

f(X) when is_integer(X); is_float(X) -> X*X;
f(_) -> sam_durak.
, чего вообще в эрланге никто не делает ибо нафиг не нужно. А теперь внимание, если ты сейчас начнёшь мне говорить, что в твоих сплюсах можно сделать так вернув код ошибки, я тебе скажу что тебе придётся писать кучу ифов и свичей, т.е. говнокодить по обезъяни. А если ты мне скажешь про throw sam_durak, то я тебе напомню, что тебе как минимум необходимо определить тип sam_durak, что при само по себе в далёкой перспективе задолбёт, а во-вторых напомни мне пожалуйста причины использовать сплюс, ах да - производительность. Производительность'n'исключения, помноженные на raii и раскрутку стека - вот веселуха! Сплошная производительность, да.

И да, man dyalizer уже наконец.

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

man dyalizer уже наконец.

Долго объяснять про то, как ловко Эрланг обходится без статической типизации, а потом ненавязчиво отослать к костылю, реализующему эту самую типизацию.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Всё верно. А что тебе не нравиться? Ты бы ещё придрался к отсутствию знака пунктуации во фразе „то тебе как минимум необходимо определить тип sam_durak“.

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

А что тебе не нравиться?

То, что ты -тся и -ться не освоил, а еще пытаешься кукарекать про ненужность плюсов.

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

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

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

Я ждал, что ты это напишешь. А теперь расскажи,

1) сколько строк было в самом большом эрланг-проекте, с которым ты работал

2) сколько времени он писался

3) сколько человек над ним работало

t. работаю с огромным проектом на этом недоязычке и знаю кое-что о масштабировании

P.S.

Если тебе нужна защита от дурака, ты пишешь:

Руками писать проверку типов

madotsuki_vomit.jpg

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

А теперь внимание, если ты сейчас начнёшь мне говорить, что в твоих сплюсах можно сделать так вернув код ошибки, я тебе скажу что тебе придётся писать кучу ифов и свичей,

P.P.S. Да ты и верно ущербный! Чтобы сделать такое в плюсах, мне не нужно писать ровно ни одной строчки, ибо статическая типизация для того и нужна.

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

не хочу все показывать посторонним людям

а RMS завещал делиться!

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

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

Серьёзно что ли? http://ideone.com/5S9Gxe

anatoly
()

.hpp инклюдить уже предлагали? а... .cpp... инклюдить? :) Самые хитрые инклюдят .inl

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

Всегда. Мы тут из окопа не вылезаем.

Pavval ★★★★★
()

А как быть допустим, если я хочу либу сделать и при этом не хочу вот так писать?

Шаблоны «раскрываются» на этапе канпеляции. То есть генерируется ровно столько типов с шаблона, сколько было указано типов при инстанциировании шаблона (ну и наплел). Проще говоря:

template <typename T> class Class;

Class<int> cint;
Class<char> cint;
На компиляции такого кода будет созданно два новых типа.

В итоге: ты можешь хранить шаблонный класс только в виде исходников (ведь в объектных файлах уже имеем сгенерированные типы). Это в свою очередь означает, что либо без таких «костылей» никак, либо ты не сможешь зашить свой шаблон в библиотеку.

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

Было для этого ключевое слово export, которое гордо поддерживал только один компилятор.

Нихрена он, на самом деле, не поддерживал. Всё равно при использовании этого шаблонного класса все соответствующие исходники должны были быть доступны.

Miguel ★★★★★
()

Пойми, шаблоны — это просто макросы. Ничего больше. Макросы сами по себе не компилируются. Так что фигли.

Возьми язык с настоящими дженериками, их можно откомпилировать и спрятать. Haskell, OCaml, Scala, C#, Java — тысячи их.

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

Блин, да будь моя воля, Go бы взял(очень мощный и простой оказался) и не было бы никакой магии с классами, но пока я в его Qt разобрался бы и возможно наладил связь с Creator'ом прошло бы много времени. А мне уже скоро проект закрывать.

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

Ты не понял

Я понял.

то, что он назвал „падучее“ на самом деле не то же самое, что и „падучее“ в терминах сплюса

Похоже, это ты не понял. Он говорит (и я тоже), что программа на Эрланге может содержать ошибки, которые тривиально отлавливаются любым компилятором статически типизированного языка.

Я же не кричу, что сплюс ущербный из-за того, что там выкидывают эксепшены, правда?

Еще раз - речь не об этом. Речь о том, что программа на Эрланге (и любом динамически типизированном языке) может «выкидывать исключения» на тривиально обнаруживаемые вещи.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от nanoolinux

Там часть, соответствующая твоему, занимает не 40, а 15 строк.

Но как выше уже сказал анон смысла на С++ такое ноль, т.к. эта та ошибка, которая должна отлавливаться на этапе компиляции.

Ну и код тот можно сократить до трёх строк.

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

http://ideone.com/QwdO6D

А вот рабочий:

http://ideone.com/vzKdgA

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

На самом деле безопасная реализация (внезапно!) будет выглядеть так:

template <typename T>
T foo(T a, T b) {
  return a*b;
}

Ну а ежели хочется совсем перестраховаться, или тайпклассы хаскеля не дают покоя, то можно воспользоваться type_traits, но мне не охота вспоминать, как это делается.

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

Согласен.

Т.е. целевой эрланговский код сокращаяется до одной строчки:

template <typename T> T f(T v) { return v*v; }

Убедительная победа С++ над Эрлангом!

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