开发者

Explicit specialization in non-namespace scope [duplicate]

This question already has answers here: C++ syntax for explicit specialization of a template function in a template class? (9 answers) 开发者_StackOverflow中文版 Closed 8 years ago.
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?


VC++ is non-compliant 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 due to C++03, §14.7.3/3, 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);
    }
};


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>)
  {

  }
};


Just take the template specialization outside the class declaration. gcc doesn't allow inline template specialization.

As another option, just deleting line template<> seems to work for me.


Even better: you can combine partial specialisation with default template arguments. This way modification to the VC++ code are minor, because calls to the specialised function do not need to be modified.

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

template <class Dummy=int>
void Verify<int, Dummy>(int, int[])
{
}


You may not be able to explicitly specialize the member template, but you can partially specialize it. If you add a second parameter "int dummyParam" and also add it to the specialization, it should work with both compilers.

Not that I knew this more than 10 seconds ago, but googling on the same error, I ran into this link and it worked for my member template specialization.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜