模板类成员特化声明

发布于 2024-08-26 08:39:05 字数 1835 浏览 11 评论 0原文

当我在模板类中专门化一个(静态)成员函数/常量时,我​​对声明的去向感到困惑。

这是我要做什么的示例 - 直接来自 IBM 关于模板专业化的参考

===IBM 会员专业化示例===

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

int main() {
   X<char*> a, b;
   X<float> c;
   c.f(10); // X<float>::v now set to 20
}

问题是,如何将其划分为头文件/cpp 文件?通用实现显然在标头中,但是专业化呢?

它不能放在头文件中,因为它是具体的,导致多个定义。但是,如果它进入 .cpp 文件,调用 X::f() 的代码是否知道专门化,或者它可能依赖于通用 X::f() ?

到目前为止,我仅在 .cpp 中进行了专门化,标头中没有声明。我在编译甚至运行我的代码时都没有遇到问题(在 gcc 上,目前不记得版本),并且它的行为符合预期 - 识别专业化。但是 A) 我不确定这是正确的,我想知道正确的是什么,B) 我的 Doxygen 文档很不稳定并且非常具有误导性(稍后将在 a moment 中详细介绍)问题)。

对我来说最自然的是这样的,在标头中声明专业化并在 .cpp 中定义它:

===XClass.hpp===

#ifndef XCLASS_HPP
#define XCLASS_HPP

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

/* declaration of specialized functions */
template<> char* X<char*>::v;
template<> void X<float>::f(float arg);

#endif

===XClass.cpp===

#include <XClass.hpp>

/* concrete implementation of specialized functions */
template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

...但是我有不知道这是否正确。有什么想法吗?

When I specialize a (static) member function/constant in a template class, I'm confused as to where the declaration is meant to go.

Here's an example of what I what to do - yoinked directly from IBM's reference on template specialization:

===IBM Member Specialization Example===

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

int main() {
   X<char*> a, b;
   X<float> c;
   c.f(10); // X<float>::v now set to 20
}

The question is, how do I divide this into header/cpp files? The generic implementation is obviously in the header, but what about the specialization?

It can't go in the header file, because it's concrete, leading to multiple definition. But if it goes into the .cpp file, is code which calls X::f() aware of the specialization, or might it rely on the generic X::f()?

So far I've got the specialization in the .cpp only, with no declaration in the header. I'm not having trouble compiling or even running my code (on gcc, don't remember the version at the moment), and it behaves as expected - recognizing the specialization. But A) I'm not sure this is correct, and I'd like to know what is, and B) my Doxygen documentation comes out wonky and very misleading (more on that in a moment a later question).

What seems most natural to me would be something like this, declaring the specialization in the header and defining it in the .cpp:

===XClass.hpp===

#ifndef XCLASS_HPP
#define XCLASS_HPP

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

/* declaration of specialized functions */
template<> char* X<char*>::v;
template<> void X<float>::f(float arg);

#endif

===XClass.cpp===

#include <XClass.hpp>

/* concrete implementation of specialized functions */
template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

...but I have no idea if this is correct. Any ideas?

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

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

发布评论

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

评论(4

匿名的好友 2024-09-02 08:39:05

通常,您只需按照 dirkgently 的说法在标头中定义专业化 inline 即可。

如果您担心编译时间或代码膨胀,您可以在单独的翻译单元中定义专业化:

// x.h:
template<class T> struct X {
    void f() {}
}

// declare specialization X<int>::f() to exist somewhere: 
template<> void X<int>::f();

// translation unit with definition for X<int>::f():
#include "x.h"
template<> void X<int>::f() {
    // ...
}

所以是的,您的方法看起来不错。请注意,您只能通过完全专业化来执行此操作,因此这样做通常是不切实际的。

有关详细信息,请参阅Comeaus 模板常见问题解答

Usually you'd just define the specializations inline in the header as dirkgently said.

You can define specializations in seperate translation units though if you are worried about compilation times or code bloat:

// x.h:
template<class T> struct X {
    void f() {}
}

// declare specialization X<int>::f() to exist somewhere: 
template<> void X<int>::f();

// translation unit with definition for X<int>::f():
#include "x.h"
template<> void X<int>::f() {
    // ...
}

So yes, your approach looks fine. Note that you can only do this with full specializations, thus it is often impractical to do this.

For details, see e.g. Comeaus template FAQ.

清引 2024-09-02 08:39:05

将它们全部放入 hpp 文件中。使专业化和您在类外部定义的任何内容内联——这将处理多个定义。

Put them all in a hpp file. Make the specializations and anything you define outside the class inline -- that'll take care of multiple definitions.

鲜肉鲜肉永远不皱 2024-09-02 08:39:05

回答您的问题之一:是调用 X::f() 的代码知道专门化,还是可能依赖于通用 X::f()?

如果编译器看到一个定义,符合它的要求,那么它就会使用它。否则它将生成正常的函数调用。

在第一个代码片段中,您为 X::f(T arg) 提供通用定义,因此编译器将为除 < 之外的任何 T 实例化该定义。代码>浮动。

如果您要省略泛型定义,那么编译器将生成对 X::f(double) 的调用,并且链接器将搜索可能以链接器错误。

总结一下:您可以在标题中包含所有内容,因为作为模板,您不会获得多个定义。如果您只有声明,则需要在其他地方进行定义,以便链接器稍后查找。

To answer one of your questions: is code which calls X::f() aware of the specialization, or might it rely on the generic X::f()?

If the compiler sees a definition which matches its requirements, then it will use it. Else it will generate normal function calls.

In your first code snippet, you supply a generic definition for X<T>::f(T arg), so the compiler will instantiate that for any T apart from float.

If you were to omit the generic definition, then the compiler would generate calls to, say, X<double>::f(double) and the linker would go searching for the definition which might end with a linker error.

To summarise: You can have everything in headers, because as templates you won't get multiple definitions. If you only have declarations, you will need definitions elsewhere for the linker to find later.

黎夕旧梦 2024-09-02 08:39:05

使用模板 void X::f(float arg) { v = arg * 2; } 相反。

Using template void X<float>::f(float arg) { v = arg * 2; } instead.

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