пользовательскими функциями, а всё остальное — библиотечное. Сейчас код не компилируется из-за того, что пользователь написал sfinae-unfriendly foo1
Способы заставить код компилироваться:
1) пользователь просто убирает вычисление noexcept
2) пользователь пишет foo1 правильно
3) мы со стороны библиотеки переписываем bar так, чтобы исключить вызов foo1 при возможности вызвать foo2
Должен ли я как разработчик библиотеки предпочесть третий вариант решения? Или же написание корректного кода должно быть ответственностью пользователя? Ведь третье решение скрывает проблему, а не решает её
я правильно понимаю, что foo1 вызывается не потому, что bar_impl(double) выбран, а как часть процесса разрешения перегрузки/инстанциации шаблона?
Да, именно так
мне кажется, что запрещать пользователю вычислять noexcept это плохой вариант, потому что не могу придумать случай, когда такой контракт будет разумен третий вариант выглядит как эмуляция SFINAE вне контекста перегрузки. это, наверное, может иметь смысл в каких-то случаях, но не проще ли тогда на нормальную перегрузку перейти?
Дело в том, что проблема пользователя не в вычислении noexcept, а в том, что он написал функцию, которая вне sfinae-контекста делает что-то с заранее неизвестным типом, и это стреляет в ногу таким странным образом. Более правильным решением со стороны пользователя было бы сделать вызов foo1 ill-formed в sfinae-контексте (например, взять второй мой вариант решения или повесить концепт на Fn). Т.е. правильным контрактом было бы требовать от пользователя предоставлять sfinae-friendly реализации функции На нормальную перегрузку перейти не получится, ибо это минимально-воспроизводимый пример, в оригинале одна foo, имеющая две перегрузки с разными тегами и весь набор шаблонной магии, включая очень глубокие рекурсии
А нужен ли trail type в bar_impl? Если использовать просто вывод типа через auto оно собирается.
очень зависит от тела bar_impl trail return type с конкретным decltype в этом отношении куда надежнее
Тогда мы сами напишем sfinae-unfriendly имплементацию на стороне библиотеки. Для корректной пользовательской реализации мы бы хотели получить ошибку внутри decltype(), а не в теле bar_impl. Потому что в первом случае это ещё не гарантированная ошибка компиляции, а во втором случае — уже гарантированная
гм. Спасибо, я уже не часто закапываюсь в шаблоны, но кажется теперь осознал.
Обсуждают сегодня