У нас есть большая библиотека геометрии вычислений. В его ядре есть проблема. У нас есть определения скалярных подсказок и вспомогательных аксессоров в виде свободных функций, чтобы просто написать cg::epsilon<T>()
вместо cg::scalar_traits<T>::epsilon
, Но проблема в том, что под vs2008 и vs2010 он иногда утверждает, что не может вывести параметр шаблона для T
в cg::epsilon<T>
, На других компиляторах в LWS работает отлично.
Сокращенная версия для воспроизведения:
namespace cg
{
template<class S>
S epsilon();
template<>
double epsilon<double>() {return 1;}
template<>
float epsilon<float>() {return 1;}
template<class S>
bool eq(S a, S b, S eps = cg::epsilon<S>())
{
return true;
}
}int main(int argc, char* argv[])
{
cg::eq(0.0, 0.0);
cg::eq(0.0f, 0.0f);
return 0;
}
Есть ли обходные пути, чтобы заставить работать аксессоры?
PS: мы используем cg::scalar_traits<S>::epsilon()
, это помогает, где ошибка происходит, но это слишком многословно
Исследование:
Даже объявлен как
template<class S>
bool eq(S a, S b, S eps = cg::epsilon<double>())
Компилятор жалуется, что не может вывести S для cg :: epsilon.
Я предполагаю, что компилятор использует параметр по умолчанию S eps = cg::epsilon<S>()
за вычетом S
, Для этого нужно взглянуть на декларацию cg::epsilon<S>()
но в это время он не знает S
еще.
Обходной путь избегает значения по умолчанию для третьего параметра и добавляет две различные перегрузки: первый принимает три аргумента (a
, b
а также eps
) а второй занимает всего два (a
а также b
). Последний получает eps
от cg::epsilon<S>()
(в это время S
уже было выведено) и делегирует вызов первому, как показано в приведенном ниже коде:
template<class S>
bool eq(S a, S b, S eps)
{
return true;
}
template<class S>
bool eq(S a, S b)
{
S eps = cg::epsilon<S>();
return eq(a, b, eps);
}
Других решений пока нет …