5

In my application (compiled under Visual C++ 2010), I have code like this in a header file:

// example.h
#pragma once

#include <limits>

namespace myspace
{

// A generic equality test
template<typename T> inline bool equal(
    const T &v1, 
    const T &v2, 
    const T &eps = std::numeric_limits<T>::epsilon())
{
    return (v1 == v2);
}

// Template specialization for floating-point numbers
template<> bool equal<float>(
    const float &v1, 
    const float &v2, 
    const float &eps);

// A generic equality test for finite-precision real number representations (with epsilon)
template<typename T> inline bool realEqual(
    const T &p, 
    const T &q, 
    const T &eps = std::numeric_limits<T>::epsilon())
{
    return (fabs(p - q) < eps);
}

} // namespace myspace

...and some code in a .cpp file:

// example.cpp
#include "example.h"

using namespace std;
using namespace myspace;

// equal-macro specialization that calls the appropriate equality test function for real numbers
template<> bool myspace::equal<float>(
    const float &v1, 
    const float &v2, 
    const float &eps)
{
    return (realEqual(v1, v2, eps));
}

int _tmain(int argc, _TCHAR* argv[])
{
    float a,b;
    bool x = realEqual(a,b); // OK
    bool x = equal(a,b); // compile error
    return 0;
}

This fails to compile, giving me:

------ Build started: Project: test, Configuration: Debug Win32 ------
test.cpp
c:\users\ninja\documents\visual studio 2010\projects\test\test\test.h(10): error C2589: '::' : illegal token on right side of '::'
c:\users\ninja\documents\visual studio 2010\projects\test\test\test.h(10): error C2059: syntax error : '::'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The offending line is the one with the definition of the "eps" parameter's default value for the equal() function.

A google search revealed people've had similar "illegal token" errors with other functions from numeric_limits, namely min() and max(), but these were due to some #define present in Windows-specific c++ standard library header files, which defined "min" and "max" for some legacy reasons. No mention about epsilon(), and I'm absolutely stumped about why I'm getting an error here. Anyway, changing the function name from "equal" to something like "smartEqual" still gives the same error, so the name is obviously not the issue. What is?

Thanks!

neuviemeporte
  • 6,310
  • 10
  • 49
  • 78
  • If you remove the default parameter it compiles? – Seth Carnegie Apr 27 '12 at 00:29
  • As a data point, the Comeau online compiler (http://www.comeaucomputing.com/tryitout) compiles it fine if you include the `cmath` header and get rid of the extraneous `bool` before the second `x` (well, and change `_tmain`'s signature appropriately and put it all in a single file...) – Stuart Golodetz Apr 27 '12 at 00:29
  • As another data point, g++ on Lion also compiles that minimally-modified version fine. – Stuart Golodetz Apr 27 '12 at 00:32
  • @Seth: Yes, removing the default parameter makes it compile, but I really want that value there since it's desirable most of the time. Seems to me like equal and realEqual are pretty much the same thing, so why does one work and the other not? – neuviemeporte Apr 27 '12 at 00:38
  • @Stuart: I added under VS2010, no change. – neuviemeporte Apr 27 '12 at 00:39
  • @neuviemeporte: Yes, it's a bug apparently - see my answer below. – Stuart Golodetz Apr 27 '12 at 00:40

1 Answers1

8

It looks like it's caused by this bug in Visual Studio:

https://connect.microsoft.com/VisualStudio/feedback/details/583081/

See also here:

template function specialization default argument

Community
  • 1
  • 1
Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
  • 2
    Thanks! I fixed the issue by creating an additional template function getEpsilon() { return numeric_limits::epsilon(); } and initializing the default parameter using it. – neuviemeporte Apr 27 '12 at 00:52
  • 2
    "Given this, we are planning not to fix this bug for our next release, in favor of more severe issues for which there is no workaround." Ah, Microsoft. Why not fix both and delay the release for a day? – Seth Carnegie Apr 27 '12 at 00:55
  • @Seth: Probably because: "Unfortunately, fixing this area of our compiler is costly, prone to introducing more severe issues, and may cause issues in existing (malformed but operational) code.". I don't envy those guys that luggage of broken legacy code. That said, in a way it's nice to know it wasn't I who screwed up for once. ;) – neuviemeporte Apr 27 '12 at 01:03
  • @neuviemeporte That's no (good) excuse. Do it right and fix your code Microsoft! I do feel for them though, they are a massive company and steering a ship that big isn't easy. – Seth Carnegie Apr 27 '12 at 01:04
  • Now I've hit an another bug and can't use the function twice... :/ See http://stackoverflow.com/questions/10343741/why-does-using-this-c-function-twice-in-one-line-cause-a-compile-error – neuviemeporte Apr 27 '12 at 02:10
  • Microsoft link is no longer valid. – GhostRavenstorm Aug 10 '19 at 15:13