SVV>предположим, в качестве T будут использоваться типы char и wchar, как и в качестве T2. Как прописать специализацию не только по Т2?
template<> внутри класса не нужны.
Специализацию Test<char> придется определить полностью, так как для компилятора это отдельный класс, никак не связанный с общим шаблоном Test<T>, и никаких ожиданий по методам класса, которые должны быть определены, у него нет.
Здравствуйте, SVV, Вы писали:
SVV>предположим, в качестве T будут использоваться типы char и wchar, как и в качестве T2. Как прописать специализацию не только по Т2?
И это именно специализация функций-членов, без специализации самого шаблонного класса.
Такая форма специализации, конечно же, допустима и для конструкторов. Поэтому в исходном примере достаточно просто заменить специализацию конструкторов на перегрузку:
Здравствуйте, rg45, Вы писали: R>На самом деле, не обязательно. В С++ существует и такая форма специализации для функций-членов шаблонных классов: R>И это именно специализация функций-членов, без специализации самого шаблонного класса.
Про это я знал, но ТС определил конструкторы в теле класса, а затем вне тела для специализации. Поэтому я и подумал, что ему потребуется определить специализацию. R>Такая форма специализации, конечно же, допустима и для конструкторов. Поэтому в исходном примере достаточно просто заменить специализацию конструкторов на перегрузку:
Здравствуйте, andyp, Вы писали:
A>Специализацию Test<char> придется определить полностью, так как для компилятора это отдельный класс, никак не связанный с общим шаблоном Test<T>, и никаких ожиданий по методам класса, которые должны быть определены, у него нет.
Можно же специализировать только один метод?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, SVV, Вы писали:
SVV>предположим, в качестве T будут использоваться типы char и wchar, как и в качестве T2. Как прописать специализацию не только по Т2?
Просто интересно, а зачем это надо?
Ну, грубо говоря, если мы как-то особо работаем с whar_t, например, и как-то ещё иначе особо с char, то может лучше иметь шаблон, кторй работает как-то в целом, а для этих типав специализирован, а потом уже на этом шаблоне реализовывать конструктор class Test?
То есть, я вполне верю, что есть ситуации, когда надо и так, как надо тебе, но мне интересно каковы они.
Не поделишься?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, SVV, Вы писали:
SVV>>предположим, в качестве T будут использоваться типы char и wchar, как и в качестве T2. Как прописать специализацию не только по Т2?
E>Просто интересно, а зачем это надо? E>Ну, грубо говоря, если мы как-то особо работаем с whar_t, например, и как-то ещё иначе особо с char, то может лучше иметь шаблон, кторй работает как-то в целом, а для этих типав специализирован, а потом уже на этом шаблоне реализовывать конструктор class Test?
E>То есть, я вполне верю, что есть ситуации, когда надо и так, как надо тебе, но мне интересно каковы они. E>Не поделишься?
Делюсь:
если делается класс для работы как с char так и с wchar_t то конструкторов должно быть минимум 4:
для char версии класса:
Test(const char *) — обычная инициализация
Test(const wchar_t *) — инициализация конвертацией wide строки в char
для wchar_t версии класса:
Test(const char *) — инициализация конвертацией char строки в wide
Test(const wchar_t *) — обычная инициализация
те же минимум 4 operator= (&), operator=(&&) и конструкторы Test (&&)
и да, основной функционал запихнул в глобальные inline функции. Надеюсь, компилятор прооптимизирует. Просто сейчас есть TestA версия и TestW версия отдельно, и я смотрю что они сильно похожи, правишь что-то в одном классе и надо лезть аналогичные правки делать в другом. И хорошо если классов 2 а не больше.
Здравствуйте, SVV, Вы писали:
SVV>Делюсь: SVV>если делается класс для работы как с char так и с wchar_t то конструкторов должно быть минимум 4: SVV>для char версии класса: SVV>Test(const char *) — обычная инициализация SVV>Test(const wchar_t *) — инициализация конвертацией wide строки в char SVV>для wchar_t версии класса: SVV>Test(const char *) — инициализация конвертацией char строки в wide SVV>Test(const wchar_t *) — обычная инициализация
SVV>те же минимум 4 operator= (&), operator=(&&) и конструкторы Test (&&)
Не ясно зачем тут вообще шаблонный конструктор, если честно... :xz;
SVV>и да, основной функционал запихнул в глобальные inline функции. Надеюсь, компилятор прооптимизирует. Просто сейчас есть TestA версия и TestW версия отдельно, и я смотрю что они сильно похожи, правишь что-то в одном классе и надо лезть аналогичные правки делать в другом. И хорошо если классов 2 а не больше.
А как предполагается обобщать, если классов больше? Имеется в виду что есть ещё и TryA и TryW, DoA и DoW и т. д, или что, кроме A и W есть X, Y, Z?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, SVV, Вы писали:
SVV>>Делюсь: SVV>>если делается класс для работы как с char так и с wchar_t то конструкторов должно быть минимум 4: SVV>>для char версии класса: SVV>>Test(const char *) — обычная инициализация SVV>>Test(const wchar_t *) — инициализация конвертацией wide строки в char SVV>>для wchar_t версии класса: SVV>>Test(const char *) — инициализация конвертацией char строки в wide SVV>>Test(const wchar_t *) — обычная инициализация
SVV>>те же минимум 4 operator= (&), operator=(&&) и конструкторы Test (&&)
E>Не ясно зачем тут вообще шаблонный конструктор, если честно... :xz;
Верно, достаточно прописать специализацию для Test<char> и Test<wchar>.
E>А как предполагается обобщать, если классов больше? Имеется в виду что есть ещё и TryA и TryW, DoA и DoW и т. д, или что, кроме A и W есть X, Y, Z?..
скорее что-то кроме A и W. То есть это опять A и W только немного по-другому будет работа со строками происходить. как буду обобщать еще не знаю.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, SVV, Вы писали:
SVV>>если делается класс для работы как с char так и с wchar_t то конструкторов должно быть минимум 4:
К>Как насчёт подумать в такую сторону? К>
я не совсем понял намёк, сорри. Мой уровень не достаточен. Но смысл в том чтобы сделать объект класса минимального размера. Выделать 4 байта под deleter пока не хочется. Но про allocator/deallocator уже что-то думается. Надо будет как-то через параметр шаблона что-то передавать и не сохраняя как член класса использовать в методах. Если это возможно.
Здравствуйте, SVV, Вы писали:
SVV>я не совсем понял намёк, сорри. Мой уровень не достаточен. Но смысл в том чтобы сделать объект класса минимального размера. Выделать 4 байта под deleter пока не хочется. Но про allocator/deallocator уже что-то думается. Надо будет как-то через параметр шаблона что-то передавать и не сохраняя как член класса использовать в методах. Если это возможно.
Намёк такой, что сделать класс сам по себе минимально специализируемым. Один шаблон и всё.
А места для конкретизации вынести за его пределы.
Я не знаю, нужно ли кастомизировать владение. Это примерно по аналогии с макросами A2W и т.п. в MFC/ATL/WTL — если строка того же типа, то прозрачно держим указатель на оригинал, а если другого — создаём копию, которую потом удалим.
Если нужно — тогда будет деаллокатор-или-пусто. В конце концов, это не 4 байта, а 1 (булев флажок), — хотя всё равно, с учётом выравнивания, вырастет до 4 байтов.
Если копия строки создаётся всегда, — то не нужно, делаем безусловный деструктор.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, SVV, Вы писали:
SVV>>я не совсем понял намёк, сорри. Мой уровень не достаточен. Но смысл в том чтобы сделать объект класса минимального размера. Выделать 4 байта под deleter пока не хочется. Но про allocator/deallocator уже что-то думается. Надо будет как-то через параметр шаблона что-то передавать и не сохраняя как член класса использовать в методах. Если это возможно.
К>Намёк такой, что сделать класс сам по себе минимально специализируемым. Один шаблон и всё. К>А места для конкретизации вынести за его пределы.
К>Я не знаю, нужно ли кастомизировать владение. Это примерно по аналогии с макросами A2W и т.п. в MFC/ATL/WTL — если строка того же типа, то прозрачно держим указатель на оригинал, а если другого — создаём копию, которую потом удалим. К>Если нужно — тогда будет деаллокатор-или-пусто. В конце концов, это не 4 байта, а 1 (булев флажок), — хотя всё равно, с учётом выравнивания, вырастет до 4 байтов. К>Если копия строки создаётся всегда, — то не нужно, делаем безусловный деструктор.
на длину строки отведено 4 байта. некоторые типы строк всегда будут содержать только указатель и не освобождать данные. в таких случаях char -> wchar преобразование невозможно. в других строках старший бит длины определяет надо ли освобождать данные. Таким образом, длина строки только 2^31, чего в большинстве случаев достаточно.
Здравствуйте, SVV, Вы писали:
SVV>на длину строки отведено 4 байта. некоторые типы строк всегда будут содержать только указатель и не освобождать данные. в таких случаях char -> wchar преобразование невозможно. в других строках старший бит длины определяет надо ли освобождать данные. Таким образом, длина строки только 2^31, чего в большинстве случаев достаточно.
Вот это вообще не понял, при чём. Строка с префиксом-длиной, как в BSTR или паскале-дельфи? И с политиками времени жизни, как в ObjC?
Ну так тем лучше. Хранить только указатель на строку, удалять или нет с оглядкой на флажки в префиксе.
Тогда всё, что нужно — это написать 4 функции копирования.