Question

template <typename T> void function(T arg1, 
    T min = std::numeric_limits<T>::min(),
    T max = std::numeric_limits<T>::max())
{
}

template <> void function<int>(int arg1, int min,int max)
{
}

int main(int argc,char* argv[])
{
    function<int>(1);
}

it give syntax error C2689 and C2059 on function default argument line on :: token. but without specialization, it doing fine. and if I change default argument and still doing specialization:

template <typename T> void function(T arg1, 
    T min = T(0),
    T max = T(1))
{
}
template <> void function<int>(int arg1, int min,int max)
{
}

the problem gone too.

now if I use it like this: function<int>(1,2,3); or function<float>(1.0f) its fine, so it seems that if template function is specialized, we must rewrite the default argument when call it?

but on my second case, where i replace std::numeric_limits<T>::.. with T(..) there no syntax error when calling function<int>(1), why is that?

(I'am using Visual Studio 2010 x64)

as original problem is because of bug, the question now changed to how to workaround it?

Was it helpful?

Solution

There is nothing wrong with the code; Comeau Online, Intel C++ 11.1, and g++ 4.1.2 compile it successfully.

I would guess that it is a bug in the compiler. I recently submitted a related, but slightly different bug report against the Visual C++ 2010 compiler.


As a workaround, you can wrap the calls:

template <typename T>
T get_limits_min() { return std::numeric_limits<T>::min(); }

template <typename T>
T get_limits_max() { return std::numeric_limits<T>::max(); }

template <typename T> void function(T arg1, 
    T min = get_limits_min<T>(),
    T max = get_limits_max<T>())
{
}

Ugly? Quite.


I posted the following in response to the bug you reported on Microsoft Connect:

The primary template must have a parameter that has a default argument value. The default argument value must be a member function of a class template not in the global namespace.

The following is minimal code to reproduce:

namespace N
{
    template <typename T>
    struct S
    {
        static T g() { return T(); }
    };
}

template <typename T> void f(T = N::S<T>::g()) { }

template <> void f<>(int) { }

int main()
{
    f<int>();
}

The compiler emits the following errors, both on the line where the primary template is defined:

error C2589: '::' : illegal token on right side of '::'
error C2059: syntax error : '::'

Interestingly, there is another issue if the class template is in the global namespace. Given the following code:

template <typename T>
struct S
{
    static T g() { return T(); }
};

template <typename T> void f(T = ::S<T>::g()) { }

template <> void f<>(int) { }

int main()
{
    f<int>();
}

The compiler emits the following error on the line on which the primary template is defined:

error C2064: term does not evaluate to a function taking 0 arguments

Both of these example test cases are well-formed C++ programs.

OTHER TIPS

As answered here at https://stackoverflow.com/a/13566433/364084 and https://stackoverflow.com/a/27443191/364084, this is due to min and max macro defined in windows header. The following code should work by preventing the macro expansion:

template <typename T> void function(T arg1, 
    T min = (std::numeric_limits<T>::min)(),
    T max = (std::numeric_limits<T>::max)())
{
}

template <> void function<int>(int arg1, int min,int max)
{
}

int main(int argc,char* argv[])
{
    function<int>(1);
}

It is succeesfully compiled... in Comeau Online ,http://codepad.org,EDG Compiler ,and G++ .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top