为什么在一行中两次使用此C++函数会导致编译错误?

neu*_*rte 15 c++ type-conversion visual-studio default-arguments

我试图在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
Run Code Online (Sandbox Code Playgroud)

源文件:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

报告错误如下:

------ Build build:项目:测试,配置:调试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'
没有可以进行此转换的上下文

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

我不明白为什么会这样.将"eps"从引用类型更改为直接值类型可以修复它,但我希望我知道发生了什么.

谢谢!

Fra*_*ser 13

我想你现在已经遇到了这个VS10漏洞.

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

您可以通过更改smartEqual为:来避免默认值(这似乎是VS10的主要问题):

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

并简单地专门为float(和double)这样:

template<> bool myspace::smartEqual<float>(
    const float &v1, 
    const float &v2)
{
    return (fabs(v1 - v2) < std::numeric_limits<float>::epsilon());
}
Run Code Online (Sandbox Code Playgroud)


另一个选项是更改epsilon参数以传递值:

template<typename T> inline bool smartEqual(
    const T &v1, 
    const T &v2, 
    T eps = epsilon<T>())
{
    return (v1 == v2);
}
Run Code Online (Sandbox Code Playgroud)