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

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


person kassak    schedule 20.03.2013    source источник


Ответы (1)


Я предполагаю, что компилятор использует параметр по умолчанию 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);
}
person Cassio Neri    schedule 20.03.2013
comment
Ваши догадки звучат реалистично. Но писать обертки хуже, чем использовать cg::scalar_traits<S>::epsilon. А также, если вы правы, почему использование трейтов не вызывает эту ошибку? - person kassak; 20.03.2013
comment
@kassak: я бы также предпочел не писать оболочку и использовать параметр по умолчанию точно так же, как вы (я считаю, что ваш код соответствует стандарту). Написание оболочки является нежелательным обходным путем :-(. Я не понимаю, что вы имеете в виду, говоря, что использование признаков не вызывает эту ошибку, но в любом случае я не могу точно сказать, что происходит, поскольку я не вижу код Visual Studio ;- ) Я могу только догадываться. - person Cassio Neri; 20.03.2013
comment
Да, я понимаю. Использование признаков не вызывает эту ошибку, я имел в виду, что использование cg::scalar_traits<S>::epsilon() вместо cg::epsilon<S>() не вызывает эту ошибку, но это слишком многословно =( cg::epsilon просто возвращает cg::scalar_traits<S>::epsilon() и было сделано, чтобы сделать код более понятным. Поскольку cg::epsilon<S>() не только короче, но и is -- эпсилон типа S - person kassak; 20.03.2013