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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3052579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:53:56  来源:igfitidea点击:

Explicit specialization in non-namespace scope

c++templatesgcc

提问by Mark

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:

在 g++ 下编译会出现以下错误:

Explicit specialization in non-namespace scope 'class CConstraint'

非命名空间范围“类 CConstraint”中的显式专业化

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

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

采纳答案by Georg Fritzsche

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

在这种情况下,VC++ 是不合规的——显式特化必须在命名空间范围内。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:

此外,由于 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);
    }
};

回答by Johannes Schaub - litb

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 *thisand to the outer template parameter type.

另一种解决方法是委托给一个私有函数并重载该函数。这样,您仍然可以访问*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>)
  {

  }
};

回答by bop

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

只需在类声明之外使用模板特化即可。gcc 不允许内联模板特化。

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

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

回答by vitke

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.

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

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

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

回答by M. Tibbits

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

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

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

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