views:

110

answers:

2
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?

A: 

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.

James McNellis
how do I report this bug to microsoft?
uray
@uray: You can submit it at connect.microsoft.com via that bug report link I listed; you'll have to sign in and open a new defect. If you don't want to, I'll try to reduce this issue and the issue I reported previously to a common sample and resubmit the issue. Let me know; I'm happy to help.
James McNellis
@james:I'am reporting bug right now.
uray
bug is reported at https://connect.microsoft.com/VisualStudio/feedback/details/583081/
uray
+1  A: 

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

BE Student