问题
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