Explicit specialization of C++ struct member template functions - is this a Visual Studio problem?
Asked Answered
G

1

4

I have a problem with template specialization which boils down to the following snippet:

#include <iostream>

struct Class
{
    template <unsigned int N> static void fun(double a[N], double (&x)[N+1]);
};

template <> inline void Class::fun<1u>(double a[1u], double (&x)[2u])
{
    x[0] += 0.2;
}

template <> inline void Class::fun<2u>(double a[2], double (&x)[3])
{
    x[0] += 0.4;
}

int main(void)
{
    double x[1] = {0};
    double a[2] = {0, 1};
    double b[3] = {0, 0, 1};

    Class::fun<1>(x, a);
    Class::fun<2>(a, b);
    std::cout << a[0] << " " << b[0] << std::endl;
    return 0;
}

It compiles and works correctly, displaying 0.2 0.4, in Cygwin g++ 4.3.4 and also compiles in Comeau Online compiler. However, Visual Studio C++ 2010 Express gives the following error message:

error C2910: 'Class::fun' : cannot be explicitly specialized
error C2910: 'Class::fun' : cannot be explicitly specialized

EDIT: when I changed the function to be a free function, the error message changed to

error C2912: explicit specialization; 'void fun<1>(double [],double (&)[2])' is not a specialization of a function template

So, two questions: 1. is my code legal C++ 2. if so, is this a known problem with Visual Studio C++ 2010 compiler?

Gavin answered 21/5, 2011 at 19:25 Comment(6)
This probably isn't relevant, but shouldn't parameter a be passed by reference just like x? (void fun(double (&a)[N]), ...)Vasilikivasilis
@Alan Yes, it makes the code work in VS 2010... but WHY?Gavin
Also, the old code compiled without problems in other compilers.Gavin
@quant: Without the array reference, the array dimensions don't do anything. So you could call fun<2>(x, b); fun<1>(a, a);. So yes this looks like a bug in VC++, but you have a workaround that's actually better on all compilers.Cassiopeia
Maybe it's a bug in the other compilers? I was hoping for an enlightening quotation from The Standard. The workaround is not that better, because with the reference, I don't have my array on the stack. I guess I'll switch to boost::array (which is also stack based).Gavin
This may be still broke in Visual Studio 2013. Also see Barry's answer at Explicit specialization of member function template in source file. The simple forward declaration is enough to sidestep an error about already being specialized.Kalakalaazar
S
4

Well, I'd say it is most likely legal c++ code as I compile and run it fine with:

g++ -ansi -gstabs+ -Wall -o fun fun.cpp
g++ -std=c++98 -gstabs+ -Wall -o fun fun.cpp
g++ -std=c++0x -gstabs+ -Wall -o fun fun.cpp

I'm suspecting it's the same bug mentioned here: http://msdn.microsoft.com/en-us/library/cx7k7hcf(v=vs.80).aspx

Particularly:

The explicit specialization of a member function outside the class is not valid if the function has already been explicitly specialized via a template class specialization. (C2910).

from http://msdn.microsoft.com/en-us/library/h62s5036(v=vs.80).aspx

Sheldon answered 24/5, 2011 at 17:30 Comment(8)
"Builds in g++" is not equivalent to "is legal C++".Gavin
I don't think my answer deserved a thumbs down quant_dev. Read the whole thing before thumbing. I didn't say "is legal c++".Sheldon
Well, my question was "is it legal C++".Gavin
I'm thinking the answer is 'most likely yes'. And the answer to your other question "is this a known problem with Visual Studio C++ 2010" is 'most likely yes, check the link for more info: msdn.microsoft.com/en-us/library/h62s5036(v=vs.80).aspx - sorry I couldn't be more specific.Sheldon
"The explicit specialization of a member function outside the class is not valid if the function has already been explicitly specialized via a template class specialization. (C2910)."Sheldon
But I have no template class specializations for Class. It isn't even a template. How can this be applicable here?Gavin
Sorry man. You're totally right. I was misreading the MS bug and applying it to the template function inside the class. It would kind of fit if it were to say "..explicitly specialized via a template method inside of a class specialization". Good job on the vote down :) /me resignsSheldon
Visual Studio 2008 gives this same error. The fix is to remove template<> from the definition, as @matiu's first link indicates in the last bit of sample code.Sclerosed

© 2022 - 2024 — McMap. All rights reserved.