Почему использование этой функции С++ дважды в одной строке вызывает ошибку компиляции?
Я столкнулся с некоторыми проблемами с попыткой реализовать в Visual С++ 2010 функцию шаблона макросов типа проверки равенства, которая связана с ошибкой в VS в отношении аргументов по умолчанию шаблона функции. Я исправил его, добавив значение параметра в дополнительную функцию, но теперь обнаружил, что не могу использовать эту функцию дважды в одной строке!
Заголовочный файл:
// example.h
#pragma once
#include <limits>
namespace myspace
{
// Need to define this separately to avoid a Visual Studio bug
template<typename T> T epsilon() { return std::numeric_limits<T>::epsilon(); }
// A generic equality test
template<typename T> inline bool smartEqual(
const T &v1,
const T &v2,
const T &eps = epsilon<T>())
{
return (v1 == v2);
}
// Template specialization for floating-point numbers
template<> bool smartEqual<float>(
const float &v1,
const float &v2,
const float &eps);
} // namespace myspace
Исходный файл:
// example.cpp
#include "example.h"
using namespace std;
using namespace myspace;
// equal-macro specialization for floats using epsilon
template<> bool myspace::smartEqual<float>(
const float &v1,
const float &v2,
const float &eps)
{
return (fabs(v1 - v2) < eps);
}
int _tmain(int argc, _TCHAR* argv[])
{
float a,b;
bool x = smartEqual(a,b); // works ok
bool x = smartEqual(a,b) && smartEqual(b,a); // error
return 0;
}
Ошибка сообщается следующим образом:
------ Начало сборки: Project: test, Configuration: Debug Win32 ------
test.cpp
c:\users\ninja\documents\visual studio 2010\projects\test\test\test.cpp(24): ошибка C2440: 'default argument': невозможно преобразовать из 'const float *' в 'const float &' < ш > Причина: невозможно преобразовать из 'const float *' в 'const float'
Нет никакого контекста, в котором это преобразование возможно
Строка оскорбления - это ту, где я пытаюсь дважды вызвать smartEqual(), используя логический И.
Я не понимаю, почему это происходит. Изменение "eps" от ссылочного типа до простого типа значения фиксирует его, но мне хотелось бы знать, что происходит.
Спасибо!
Ответы
Ответ 1
Думаю, вы теперь нажали эту ошибку VS10.
Ваш код компилирует OK на бета-версии VS11.
Возможно, вы можете избежать значения по умолчанию (что, по-видимому, является основной проблемой для VS10), изменив smartEqual
на:
template<typename T> inline bool smartEqual(
const T &v1,
const T &v2)
{
return (v1 == v2);
}
и просто специализируется на float (и double) следующим образом:
template<> bool myspace::smartEqual<float>(
const float &v1,
const float &v2)
{
return (fabs(v1 - v2) < std::numeric_limits<float>::epsilon());
}
Другой вариант - изменить параметр epsilon для передачи по значению:
template<typename T> inline bool smartEqual(
const T &v1,
const T &v2,
T eps = epsilon<T>())
{
return (v1 == v2);
}
Ответ 2
не удалось выполнить код в VS2010, но ОК в компиляторе Intel. выглядит как ошибка в VS2010
Ответ 3
После некоторого рассмотрения я решил пойти с еще одним решением, которое предложил @Fraser (хотя я получил от него вдохновение) и написал свой собственный ответ:
- Первое решение лишает меня гибкости в использовании пользовательского значения eps.
- Второе решение с передачей по значению кажется неправильным, особенно если в будущем я решит использовать эту функцию для некоторых более надуманных типов.
Поскольку VS кажется чрезмерным с ошибками в отношении значений параметров по умолчанию (только в шаблонах?), кажется, что наиболее разумной задачей является устранение проблемы путем создания двух версий smartEqual; с и без eps (используя значение по умолчанию), что в значительной степени делает то же самое, если не так кратко:
// An equality test that doesn't require the value of eps, default will be used
template<typename T> inline bool smartEqual(
const T &v1,
const T &v2)
{
return (v1 == v2);
}
// Float specialization: return (fabs(v1 - v2) < std::numeric_limits<float>::epsilon());
template<> inline bool smartEqual<float>(
const float &v1,
const float &v2);
// A custom-eps value equality test
template<typename T> inline bool smartEqual(
const T &v1,
const T &v2,
const T &eps)
{
return (v1 == v2);
}
// Float specialization: return (fabs(v1 - v2) < eps);
template<> bool smartEqual<float>(
const float &v1,
const float &v2,
const float &eps);