Обойти ошибку компилятора

У нас есть большая библиотека геометрии вычислений. В его ядре есть проблема. У нас есть определения скалярных подсказок и вспомогательных аксессоров в виде свободных функций, чтобы просто написать 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.

4

Решение

Я предполагаю, что компилятор использует параметр по умолчанию 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);
}
1

Другие решения

Других решений пока нет …