template function specialization default argument

让人想犯罪 __ 提交于 2020-01-04 13:43:44

问题


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?


回答1:


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.




回答2:


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);
}



回答3:


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



来源:https://stackoverflow.com/questions/3402338/template-function-specialization-default-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!