всем привет.
Попытался сделать простое разделение функций для enum и остальных типов и натолкнулся на не совсем понятные ошибки.
Для начала объявляю что-то типа концепции
template<typename T>
using IsEnumConcept = std::enable_if_t<std::is_enum<T>::value>;
template<typename T>
using IsNotEnumConcept = std::enable_if_t<!std::is_enum<T>::value>;
IsEnumConcept — для enum, IsNotEnumConcept — для всех остальных
Теперь пытаюсь сделать две функции, которые ничего не принимают (в реальности они принимают tuple, но для примера это не важно) и ничего не возвращают, но для enum они должны делать что-то отличное.
в данном случае компилятор выдаёт ошибку redefinition of ‘template<class T, class> void out() Вроде ошибка вполне логичная и можно успокоиться, но немного переписываем пример
и тут компилятор говорит, что всё ок, так дальше и пиши.
Во-первых, не понятно почему компилируется второй пример. Обе функции разворачиваются в void out() На лицо явное redefinition.
Во-вторых, не ясно, чем отличается первый пример от второго с точки зрения компилятора.
Первый вариант более читабелен, так что в приоритете. Хотелось бы его довести до рабочего состояния. На обоих компиляторах (студийный и gcc) поведение одинаковое, так что на них грешу в последнюю очередь.
Здравствуйте, sergii.p, Вы писали:
SP>Во-первых, не понятно почему компилируется второй пример. Обе функции разворачиваются в void out() На лицо явное redefinition.
нет. посмотрите реализацию enable_if
хотя, возможно, я неправильно понял вопрос...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, sergii.p, Вы писали:
SP>Во-первых, не понятно почему компилируется второй пример. Обе функции разворачиваются в void out() На лицо явное redefinition. SP>Во-вторых, не ясно, чем отличается первый пример от второго с точки зрения компилятора.
Разворачиваются то да, но есть нюанс.
В случае когда выражение получается ложным как is_enum для int, другая функция out просто выбрасывается из списка подходящих функций и у компилятора остаётся только один кандидат.
Поэтому и нет неоднозначностей.
Варианты решения:
1. Использовать параметр по умолчанию:
SP>Первый вариант более читабелен, так что в приоритете. Хотелось бы его довести до рабочего состояния. На обоих компиляторах (студийный и gcc) поведение одинаковое, так что на них грешу в последнюю очередь.
Вот буквальная первая же ссылка в гугде по enable_if выдает:
A common mistake is to declare two function templates that differ only in their default template arguments. This is illegal because default template arguments are not part of function template's signature, and declaring two different function templates with the same signature is illegal.
Здравствуйте, sergii.p, Вы писали:
SP>Первый вариант более читабелен, так что в приоритете. Хотелось бы его довести до рабочего состояния. На обоих компиляторах (студийный и gcc) поведение одинаковое, так что на них грешу в последнюю очередь.
Я тебе предлагаю рассмотреть небольшой рефакторинг, а именно, реализовать шаблонную функцию через вспомогательный шаблонный класс. Это достаточно распространенный подход, позволяющий обходить самые разные проблемы, связанные с тем, что шаблоны функций не допускают частичной специализации, а шаблоны классов допускают: