Я смущен тем, как работает неявное преобразование типов в отношении списков аргументов C++. В частности, у меня есть куча функций, называемых inRange (x, start, end), которые возвращают bool в зависимости от того, находится ли x между началом и концом.Преобразование неявного типа C++ в списках аргументов
[В этом описании InRange просто синтаксический сахар для (х> начать & & х < конца) - который по-прежнему хорошо, когда х длинная строка или дорогая функция - но в реальном коде есть дополнительные args для обработки открытого/закрытого характера границ.]
Я был расплывчатым о типах выше. В частности, существуют различные реализации для сравнения по целому и с плавающей запятой, а это означает, что шаблоны не очень уместны, поскольку нет лингвистической группы C++, которая отличает int/long/unsigned/size_t и т. Д. От float/double и т. Д. Поэтому я попытался использовать систему типов, определив две версии InRange с достаточно широкими типов INT/Float:
inline bool inRange(long x, long start, long end)
inline bool inRange(double x, double start, double end)
Это не поймаешь «долго долго» или подобное, но наш код использует только в большинстве двухместных и долгот. Таким образом, это выглядело довольно безопасно: я надеялся, что inRange (int, long, long) и т. Д. Неявно повысит int до конца, и все будет хорошо. Тем не менее, в случаях, когда буквенные двойники записываются sloppily для сравнения с плавающей запятой (что я хочу разрешить), например. InRange (mydouble, 10, 20), я также должен был добавить кучу явных слепков, чтобы избавиться от предупреждений компилятора и убедитесь, что используется сравнение с плавающей точкой:
inline bool inRange(double value, long low, long high) {
return inRange(value, (double)low, (double)high);
}
inline bool inRange(double value, double low, long high) {
return inRange(value, low, (double)high, lowbound, highbound);
}
...
Не так хорошо - я бы надеялся, что преобразование длинного в двойное было бы автоматическим/неявным - но нормально. Но следующее открытие действительно исказило меня: мой компилятор обнаружил InRange с три Интсом (не лонги) в качестве аргументов, и сказал:
call of overloaded ‘inRange(int&, int&, int&)’ is ambiguous
с последующим списком всех функции InRange определенной до сих пор! Итак, у C++ нет предпочтений (int, int, int) аргументов arg, которые должны быть разрешены (длинным, длинным, длинным), а не (двойным, двойным, двойным)? Действительно?
Любая помощь, чтобы вытащить меня из этой дыры, была бы очень признательна ... Я никогда бы не подумал, что что-то настолько простое, что только примитивные типы могут оказаться настолько трудными для решения. Создание полного набора ~ 1000 подписей функций с тремя аргументами со всеми возможными комбинациями числового типа не является ответом, на который я надеюсь!
Для разрешения идентификаторов использование двусмысленности типа, как долго будет: 50л, неподписанных INT: 50u, поплавок: 50.f и т.д. Но, я полагаю, что только решает случай для констант, а не переменных. –
* ... шаблоны не были действительно подходящими, так как нет лингвистической группировки C++, которая отличает int/long/unsigned/size_t и т. Д. От float/double и т. Д. ... * - Хотя это технически верно, на практике это тривиально, чтобы реализовать шаблон для общих случаев и перегрузить ту же функцию для конкретных случаев, точно так же, как Ним указал в ответе ниже. Это означает, что за пределами определенных случаев, которые вы определили для с плавающей запятой, будет использоваться общая версия (которая устранит двусмысленность). –
@ Justin ᚅᚔᚈᚄᚒᚔ: На самом деле это не так. 'std :: numeric_limits' имеет' is_integer' [ссылка] (http://www.cplusplus.com/reference/std/limits/numeric_limits/). –