Зайцев, если не сложно можешь коротко обрисовать что нужно.
да, хорошо. Потому что чувствую, что немного сумбурно вышло. Внимание, длиннопост.
Итак, для чего это нужно. Обычная либа с CSV форматом. Почему не взял готовое? Потому что всё, что я нашёл готовое - говно. Это один из немногих случаев, когда приходится садиться за написание своего качественного велосипеда и доведения его до ума.
В чём суть либы (конкретно сейчас мы говорим только про часть либы, но не суть): есть класс для записи DSV-like файлов. DSV-like - это CSV, TSV, SCSV и так далее - что придумаете похожее, то и будет писать. Что мы можем в аднном случае конфигурировать? О, список довольно большой:
- Символ(строка)-разделитель
- Символ(строка)-кавычка
- Символ(строка) конца линии
- Символ(строка) комментария
- Символ(строка) для тримминга
- Policy для выставления кавычек (то есть как ставим кавычки: всегда или только на те поле, которые без кавычек нельзя выводить. А может быть только на не числовые значения? простор для фанатзии велик)
- Policy для тримминга (триммим всё в строке, или только начало, или только конец. Или вообще не тримим)
И это вроде как не всё (я скорее всего что-то забыл). Почему так много? Потмоу что я пишу велосипеды обощённые и не хочу, чтобы кому-то пришлось ещё раз писать всю эту дрянь.
Итак, у нас есть столько параметров, и нам нужно как-то запихнуть их в класс Writer. Окей, как? На ум приходит нескольно вариантов:
1)
template <typename Delimiter, typename Quote, ...>
class Writer{bla-bla-bla};
Какая здесь проблема? Всё очень просто - Вы не сможете передать сами символы сепараторы, кавычки и так далее через параметры шаблона, вы только можете указать их типы. А сами символы вам придётся передавать уже в конструкторе, сохранять их внутри класса и работать с ними. Выглядеть это будет вот так:
Writer<char,char> writer(',', '"');
К тому же, если Вы хотите предоставить пользователю уже готовый класс для работы с тем же TSV (а в TSV в качестве сепаратора используется \t, то у вас не получится обьявить такой ТИП (так как мы не можем символы пихать в тип, потому что у нас везде typename, а не char,int,etc.)). Нам придётся давать пользователю уже готовые ОБЬЕКТЫ для работы с этим, чего делать бы очень не хотелось (так как нам же надо тогда давать интерфейс допольнительный для установки выходного потока, так как обьект уже есть). ДА и вообще, готовый обьект - дерьмо. Пользователь должен сам создать Writer тогда, когда ОН хочет, а не я. А я должен дать ему макисльно удобные средства для этого.
Вариант мне нравится.
2)
template <char Delimiter, char Quote, ...>
class Writer{bla-bla-bla};
Сразу отметаем, так как мы тут привязываемся к типам, которые я задам. А если пользователь захочет wchar_t или ещё какую-нибудь свою штуку, которая будет нормально выводится? Сразу отметаем.
3) Улучшение первого варианта через трейты
template <typename Dialect>
class Writer{bla-bla-bla};
Всё остаётся по аналогии с первым пунктом, только теперь у нас есть набор предефайненых трейтов для разных случаев жизни: TSV, CSV, SCSV, что-нибудь ещё (трейты эти я дам пользователю сам). Если пользователю не понравится, он всегда сам сможет сделать свой трейт и подпихнуть его в мой Writer. (вот пример, как это примерно будет выглядеть: https://pastebin.com/ETfS7r4K)
Проблема в том, что снова же обьекты уже трейта будут предефайнены, потому что снова же мы внутренности их инициализируем не в типе шаблона, а уже в конструкторе (подпихиваем, что там за символы внутри будут)
Мне этот вариант нравится больше всего.
Что скажете?