类模板中函数的专业化顺序是否重要

发布于 2024-09-15 12:36:51 字数 440 浏览 11 评论 0原文

考虑类似...

template<typename T>
class Vector {
  ...
  bool operator==( const Vector<float> &rhs ) {
    // compare and return
  }

  bool operator==( const Vector<T> &rhs ) {
    // compare and return
  }
  ...
 };

注意专业化如何高于非专业化版本。如果我将专用版本放在非专用版本下面Vector == 比较是否仍然按预期工作?出于某种原因,我想我记得读过,如果您在这种情况下将专业化放在下面,那么当编译器查看标头时,它将首先看到默认值,看看它是否有效,然后使用它。

Consider something like...

template<typename T>
class Vector {
  ...
  bool operator==( const Vector<float> &rhs ) {
    // compare and return
  }

  bool operator==( const Vector<T> &rhs ) {
    // compare and return
  }
  ...
 };

Notice how the specialization is above the non specialized version. If I were to put the specialized version below the non-specialized version, would a Vector<float> == comparison still work as intended? For some reason I think I remember reading that if you put the specialization below in this scenario then when the compiler looks through the header, it will see the default first, see that it works, and use that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

榕城若虚 2024-09-22 12:36:51

您的示例代码不是专门的,而是重载的。顺序确实很重要(但在您的代码中并不重要),因为函数需要在 C++ 中已知之前进行声明。因此,如果一个重载调用另一个重载,或者中间的另一个函数调用重载集,则调用可能会在不需要的地方结束。您的示例代码是有效且常见的。

出于某种原因,我想我记得读过,如果您在这种情况下将专业化放在下面,那么当编译器查看标头时,它将首先看到默认值,看看它是否有效,然后使用它。

你正在考虑以下规则

如果模板、成员模板或类模板的成员被显式特化,则应在第一次使用该特化之前声明该特化,这将导致在每个翻译单元中发生隐式实例化发生使用;无需诊断。

我忍不住引用一下标准中关于专业化的搞笑说法

函数模板、类模板、类模板的成员函数、类模板的静态数据成员、类模板的成员类、类模板的成员类模板、类模板的成员函数模板、成员的显式专业化声明的放置类模板的成员模板的函数、非模板类的成员模板的成员函数、类模板的成员类的成员函数模板等,以及类模板、非模板的成员类模板的部分特化声明的放置类、类模板的成员类模板等可以根据显式专业化声明及其在翻译单元中的实例化点的相对定位(如上文和下文所指定)影响程序是否格式良好。编写专业化时,请注意其位置;或者让它编译将是一个足以点燃其自焚的考验。

Your example code is not specializing, but overloading. The order does matter (not in your code though), because functions need to be declared before being known in C++. So if one overload calls another, or if another function in between calls the overload set, calls may end up somewhere not desired. Your example code is valid and common.

For some reason I think I remember reading that if you put the specialization below in this scenario then when the compiler looks through the header, it will see the default first, see that it works, and use that.

You are thinking of the following rule

If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

I can't help but to quote the hilarious sayings of the Standard here about specializations

The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

热鲨 2024-09-22 12:36:51

正如所写,我相信你有一个错误。你没有专门化运算符==,你正在重载它。不允许您重载这样的模板参数。

如果您的方法是一个自由函数,那么您可以对其进行专门化。例如

template <typename T>
void Foo(Vector<T> x) {
   std::cout << "x" << std::endl;
}
template <>
void Foo(Vector<float> y) {
   std::cout << "y" << std::endl;
}

...
Vector<int> intVec;
Vector<float> floatVec;
Foo(intVec); //prints x
Foo(floatVec); //prints y

,在本例中,如果您使用 Vector 调用 Foo,您将调用专用版本。

顺序在某种程度上很重要。首先,当可用时,编译器总是倾向于使用专门化形式而不是非专门化形式。之后,编译器将尝试按顺序实例化每个函数。如果可以成功编译,则将使用该专业化。如果不能,它将转到下一个。该原则称为“替换失败不是错误”(SFINAE)。 http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error 有更详细的描述。

As written, I believe you have an error. You aren't specializing operator==, you're overloading it. You aren't allowed to overload on a template parameter like that.

If your method were a free function, then you could specialize it. For instance

template <typename T>
void Foo(Vector<T> x) {
   std::cout << "x" << std::endl;
}
template <>
void Foo(Vector<float> y) {
   std::cout << "y" << std::endl;
}

...
Vector<int> intVec;
Vector<float> floatVec;
Foo(intVec); //prints x
Foo(floatVec); //prints y

In this case, if you call Foo with Vector<float>, you'll call the specialized version.

Order matters to some degree. First of all, the compiler will always favor a specialization over an unspecialized form when one is available. After that, the compiler will try to instantiate each function in order. If it can compile it successfully, that specialization will be used. If it can't, it will move on to the next one. This principle s called Substitution Failure is not an Error (SFINAE). http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error has a much more detailed description.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文