非命名空间范围内的显式特化

时间:2010-06-16 10:46:38

标签: c++ templates gcc

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

    virtual ~CConstraint()
    {
    }

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

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

在g ++下编译它会产生以下错误:

非命名空间范围'class CConstraint'

中的显式特化

在VC中,它编译得很好。任何人都可以让我知道解决方法吗?

5 个答案:

答案 0 :(得分:92)

在这种情况下,VC ++是不兼容的 - 显式特化必须在命名空间范围内。 C ++ 03,§14.7.3/ 2

  

显式特化应在模板所属的命名空间中声明,或者对于成员模板,在封闭类或封闭类模板所属的命名空间中声明。
  应该在类模板所属的名称空间中声明类模板的成员函数,成员类或静态数据成员的显式特化。

此外,您还有一个问题,即由于C ++ 03,§14.7.3/ 3 而没有明确地专门化包含类,因此无法专门化成员函数,因此一个解决方案就是让Verify()转发一个可能是专门的免费功能:

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

答案 1 :(得分:84)

另一种解决方法是委托私有函数并重载该函数。这样,您仍然可以访问*this的成员数据和外部模板参数类型。

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

  }
};

答案 2 :(得分:11)

只需在类声明之外进行模板特化。 gcc不允许内联模板专业化。

作为另一种选择,只需删除行 模板&LT;&GT; 似乎对我有用。

答案 3 :(得分:4)

更好:您可以将部分特化与默认模板参数结合使用。这种方式对VC ++代码的修改很小,因为不需要修改对专用函数的调用。

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

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

答案 4 :(得分:1)

您可能无法明确专门化成员模板,但您可以部分对其进行专门化。如果你添加第二个参数“int dummyParam”并将其添加到专门化,它应该适用于两个编译器。

不是我在10多秒前知道这一点,而是在Google上搜索同样的错误,我遇到this link并且它适用于我的会员模板专业化。