ChatGPT解决这个技术问题 Extra ChatGPT

非命名空间范围的显式专业化[重复]

这个问题在这里已经有了答案:C++ syntax for explicit specialization of a template function in a template class? (9 个回答) 7 年前关闭。

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中,它编译得很好。谁能告诉我解决方法?

请注意,这在 C++17 中不再是问题。请参阅stackoverflow.com/questions/49707184/…

c
ctor

在这种情况下,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);
    }
};

在这种情况下不合规:一如既往:)?模板和 VC++ 不能很好地混合在一起:/
从某种意义上说,它是不合规的,它会让你做一些标准通常不允许的事情——这对于一开始就符合的代码来说不是问题(你写这样的代码,对吧?~)。真正的一致性问题是它不能编译标准要求编译的东西,或者行为与指定的不同。
就像缺少两阶段查找所引起的微妙陷阱一样......:|
为什么语言开发人员会对程序员开发人员这样做?他们是否在想,How can we make this language any more difficult to read and write?
这个答案不再正确,现在允许在符合 C++14(及更高版本)编译器的类范围内进行专门化:wg21.cmeerw.net/cwg/issue727
J
Johannes Schaub - litb

另一种解决方法是委托一个私有函数并重载该函数。这样,您仍然可以访问 *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个答案。
如果我是你,我会选择这个答案。 @Johannes:您的回答非常完美,谢谢。
谢谢,谢谢,谢谢你,约翰内斯·绍布,谢谢你的回答。
这个答案比公认的答案有用得多。
自 C++11 出现以来有什么变化吗?
b
bop

只需将模板特化放在类声明之外。 gcc 不允许内联模板特化。

作为另一种选择,仅删除行模板<> 似乎对我有用。


第一句话很重要:“gcc 不允许内联模板专业化”。
删除 template<> 也对我有用。
v
vitke

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

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

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

C++03 中不允许使用默认模板参数,仅在 C++0x/11 中。
抱歉,我错了:你不能部分专门化一个函数。
@Xeo:我猜你的意思是不允许在 C++03 中使用函数? “默认模板参数是在模板参数中 = 之后指定的模板参数 (14.3)。可以为任何类型的模板参数(类型、非类型、模板)指定默认模板参数。可以在类模板声明或类模板定义中指定默认模板参数。不应在函数模板声明或函数模板定义中指定默认模板参数,也不应在模板参数列表中指定类模板成员的定义。"
M
M. Tibbits

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

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


你不能部分特化一个函数