Здравствуйте, Erop, Вы писали:
E>Возможно решат, возможно не решат. Я так думаю, что решат, но не ту.
E>Но в текущем полложении дел есть несколько пробоем.
E>1а) Никто не гарантирует тебе, что этот твой комментарий соответсвует действительности. Вдруг *на самом деле* ты требуешь от TLog чего-то ещё. Или, наоборот, чего-то пока что не требуешь?
Об этом ниже
E>1б) НИкто не гарантирует, что твой комментарий будет правильно понят пользователем. Вдруг он напишет метод int& fff()? И в текущей версии шаблона всё будет хорошо, а потом ты что-то захочешь поправить?
А формальной проверки не выполняется.
Это относится и к явным интерфейсам. Они хорошо описывают лишь сигнатуры функций. Не больше и не меньше.
Они не описывают ни семантику функций, ни требования к многопоточности и др. гораздо более сложные и тонкие моменты.
Вот ты говоришь о шаблонных функциях, что может быть int& fff(), а может быть int fff() и шаблон может это не различить.
Представь тебе дали реализовать интерфейс:
/** Интерфейс такой-то такой-то */
struct Interface
{
/** Функция, которая создаёт экземпляр SomeClass
*/
virtual SomeClass* fff() = 0;
};
Ты думаешь — элементарно. Явный интерфейс есть. Что ещё надо? Реализовал.
Потом тебе говорят "у тебя утечка, ты сам ответственнен за удаление экземплятор SomeClass, а ты их не удаляешь!"
Через день "из-за твоего кода у нас всё падает! Метод fff() должен быть потокобезопасен! Ты что не знал, это все уже знают"
Через неделю "Блин, ну ты и накосячил! Из fff() нельзя кидать исключения! Делай с ними что хочешь, но выпускать из fff() их нельзя!"
Потом "если ты не можешь создать экземпляр, ты должен возвращать -1, а не 0! ну ты блин даёшь!"
Сигнатура функции — это лишь вершина айсберга. Это самая тривиальная часть.
Забывают комментировать и проверять (или скорее просто не думают об этом) как раз самые тонкие моменты
E>1в) Не понятно что делать, когда этот коментарий устаревает. Формальных проверок или нет или они чудовищны и ненадёжны. Вот понадобилось тебе, чтобы, скажем, сделать fff возвращал const MyInt&? Что вот делать? Вычитывать весь клиентский код во всех сделвнных на этом шаблоне проектах?
см. выше. Проблема неактуальности документации не имеет ничего общего к шаблонам.
А если например функция virtual SomeClass* fff() = 0; раньше была сама ответственна за удаление созданных экземпляров, а тебе понадобилось, что бы она пересала быть ответственна и не удаляла их. Что ты будешь делать? Вычитывать весь клиентский код во всех сделанный на этом интерфейсе проектах?
Решение: реализовать прототип класса, которым можно инстанциировать шаблон не в комментарии а в коде. И в каком-то месте инстанциировать им шаблон, что бы он компилировался, но не выполнялся. Проблема устаревания и полноты решена.
Я согласен, это сложнее, чем явный интерфейс, для этого надо обладать знаниями, что бы так сделать.
Далее — static_assert — с их помощью можно проверять уже классы, которыми пользователь специализирует твой шаблон. Проверить можно много. И даже больше, чем ты можешь проверить с помощью явного интерфейса!
Согласен, это опять же сложнее. Опять же надо обладать некими знаниями.
Далее — решение уже не только для шаблонов. Оно и явным интерфейсам костыли прикрутит. Модульные тесты. Проверяем горааааздо больше, чем явный интерфейс. Проверяем, кстати, и то, что virtual SomeClass* fff() = 0; сама удаляет память, и что она потокобезопасна, и что она не уидает исключения, и что в случае ошибки она возвращает именно -1.
E>Кроме того, есть у меня такое практическое наблюдение, что когда кто-то пишет шаблон и он при этом не супер спец этого дела, то получается изделие с неясной семантикой. Обычно я не придираясь, а просто стараясь понять что и как там втыкается, задаю вопросы, которые ставят авторов в тупик
При чём здесь шаблоны?
Я видел и обычные функции из 10 строк с неясной семантикой.