tags:

views:

467

answers:

3
template<typename T>
class CConstraint
{
public:
CConstraint()
{
}

virtual ~CConstraint()
{
}

template <typename TL>
void Verify(int position, int constraints[])
{

}

template <>
void Verify<int>(int, int[])
{

}

};

Compiling this under g++ gives the following error:

Explicit specialization in non-namespace scope 'class CConstraint'

In VC, it compiles fine. Can anyone please let me know the workaround?

+6  A: 

VC++ is incompliant in this case - explicit specializations have to be at namespace scope. C++03, §14.7.3/2:

An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.
An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

Additionally you have the problem that you can't specialize member functions without explicitly specializing the containing class, so one solution would be to let Verify() forward to a, possibly specialized, free function:

namespace detail {
    template <typename TL> void Verify     (int, int[]) {}
    template <>            void Verify<int>(int, int[]) {}
}

template<typename T> class CConstraint {
    // ...
    template <typename TL> void Verify(int position, int constraints[]) {
        detail::Verify<TL>(position, constraints);
    }
};
Georg Fritzsche
*incompliant in this case*: as always :) ? Templates and VC++ don't mix that well :/
Matthieu M.
Thanks a lot :)
Mark
It's non-compliant in a sense that it will let you do something that the Standard normally doesn't allow - which isn't a problem for code that is conformant to begin with (you write such code, right? ~). The real conformance problems are when it won't compile something that the Standard requires to compile, or will behave differently from what is specified.
Pavel Minaev
Like the subtle pitfalls arising from the missing two-phase lookup ... :|
Georg Fritzsche
A: 

gcc is correct. Member template specializations have to be made in the namespace that the class belongs to. Try to change it to:

template <> void  CConstraint::Verify<int>(int, int[])
rursw1
thank you. solution provided by @Georg worked great.
Mark
+1  A: 

Another way to solve it is by delegating to a private function and overloading that function. This way you still have access to member data of *this and to the outer template parameter type.

template<typename T>
struct identity { typedef T type; };

template<typename T>
class CConstraint
{
public:

  template <typename TL>
  void Verify(int position, int constraints[])
  {
    Verify(position, constraints, identity<TL>());
  }

private:
  template<typename TL>
  void Verify(int, int[], identity<TL>)
  {

  }

  void Verify(int, int[], identity<int>)
  {

  }
};
Johannes Schaub - litb
Thanks a lot. I was looking for this also as I need to access this. Wish I could select 2 answers.
Mark