如何仅向 C++ 中的一个方法提供显式专业化;模板类?

发布于 2024-08-05 09:32:48 字数 730 浏览 7 评论 0原文

我有一个看起来像这样的模板类:

template<class T> class C
{
    void A();
    void B();

    // Other stuff
};

template<class T> void C<T>::A() { /* something */ }
template<class T> void C<T>::B() { /* something */ }

我想要的是仅为 A 提供显式专业化,同时保留 B 和“其他内容”的默认值。

到目前为止我尝试过的是

class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition

我尝试过的所有其他变体都因解析错误而失败。


我所做的:

最初的问题是显式专业化位于头文件中,因此它被转储到多个目标文件中并弄乱了链接(为什么链接器没有注意到符号的所有实例都是相同的)闭嘴?)

解决方案最终是将显式专业化从头文件移动到代码文件。然而,为了使头文件的其他用户不实例化默认版本,我需要将原型放回头文件中。然后,为了让 GCC 真正生成显式专业化,我需要在代码文件中放置一个正确类型的虚拟变量。

I have a template class that looks something like this:

template<class T> class C
{
    void A();
    void B();

    // Other stuff
};

template<class T> void C<T>::A() { /* something */ }
template<class T> void C<T>::B() { /* something */ }

What I want is to provide an explicit specialization for only A while retaining the default for B and the "other stuff".

What I have tried so far is

class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition

Every other variant I've attempted fails with parse errors.


What I did:

The original problem was that the explicit specialization was in a header file so it was getting dumped into several object files and messing up the link (Why doesn't the linker notice all the instances of the symbol are the same a just shut up?)

The solution ends up being to move the explicit specialization from the header file to a code file. However to make the other users of the header file not instance the default version, I needed to place a prototype back in the header. Then to get GCC to actually generate the explicit specialization, I needed to place a dummy variable of the correct type in the code file.

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

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

发布评论

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

评论(2

哎呦我呸! 2024-08-12 09:32:49

尝试

template<> inline void c<int>::A() { ... }
//         ^^^^^^

按照您在头文件中定义的方式进行尝试。
每个看到它的源文件都会构建它的显式版本。这会导致您的链接错误。所以只需将其声明为内联即可。

Try

template<> inline void c<int>::A() { ... }
//         ^^^^^^

As you have defined it in a header file.
Each source file that sees it will build an explicit version of it. This is resulting in your linking errors. So jsut declare it as inline.

‘画卷フ 2024-08-12 09:32:48

除了 Martin York 的内联解决方案之外,您还可以在头文件中执行以下操作:

class D { };
template<> void C<D>::A(); // Don't implement here!

并提供带有实现的 .cpp 文件:

template<> void C<D>::A() { /* do code here */ }

因此,您可以通过提供单个定义来避免多个定义。
这也有助于在发布库时将特定类型的实现隐藏在模板头文件之外。

Alternatively to Martin York's inline solution you could also do in your header file:

class D { };
template<> void C<D>::A(); // Don't implement here!

And supply a .cpp file with the implementation:

template<> void C<D>::A() { /* do code here */ }

So you avoid the multiple definitions by supplying a single one.
This is also good to hide implementations for specific Types away from the template header file when publishing the library.

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