15

我在尝试在 Visual C++ 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;
}

报错如下:

------ 构建开始:项目:测试,配置:调试 Win32 ------
test.cpp
c:\users\ninja\documents\visual studio 2010\projects\test\test\test.cpp(24 ): error C2440: 'default argument' : cannot convert from 'const float *' to 'const float &'
原因: cannot convert from 'const float *' to 'const float'
没有可以进行这种转换的上下文

违规行是我尝试使用逻辑 AND 两次调用 smartEqual() 的行。

我不明白为什么会这样。将“eps”从引用类型更改为简单的值类型可以修复它,但我希望我知道发生了什么。

谢谢!

4

3 回答 3

13

我想你现在已经遇到了这个 VS10 错误

您的代码在 VS11 Beta 上编译正常。

您可以通过更改smartEqual为:

template<typename T> inline bool smartEqual(
    const T &v1, 
    const T &v2)
{
    return (v1 == v2);
}

并且像这样专门针对浮点(和双精度):

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);
}
于 2012-04-27T02:01:50.613 回答
2

代码在 VS2010 中失败,但在英特尔编译器中正常。看起来像VS2010中的一个错误

于 2012-04-27T02:15:31.370 回答
2

经过一番考虑,我决定采用@Fraser 建议的另一个解决方案(尽管我从他那里得到了灵感)并写下我自己的答案:

  1. 第一个解决方案剥夺了我使用自定义值 eps 的灵活性。
  2. 使用按值传递的第二个解决方案感觉不对,特别是如果将来我决定将这个函数用于一些更人为的类型。

由于 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);
于 2012-04-27T03:21:18.677 回答