C ++模板专业化编译

时间:2010-07-20 16:23:48

标签: c++ dll templates compilation specialization

我将详细概述我的问题以解释我想要实现的目标,如果你想忽略我问题的细节,问题就在最后一段。

我遇到了类设计的问题,我希望将任何类型的值传递给push()pop()函数,这些函数将传递给将附加到的字符串表示形式的值。类中的字符串,有效地创建数据流。 pop()将发生相反的情况,获取流并将流前面的几个字节转换回指定的类型。

push()pop()模板与stringstream绑定是一个明显的解决方案。但是,我希望在DLL中使用此功能,我可以在其中更改字符串的存储方式(例如加密或压缩),而无需重新编译客户端。如果算法发生变化,则需要重新编译T类型的模板。

我的下一个想法是只使用pushByte()pushInt()popByte()popInt()等函数。这样我就可以在不重新编译客户端的情况下更改实现因为它们只依赖于静态接口。这没关系。但是,它不是那么灵活。例如,如果某个值从一个字节更改为一个short,则所有与该值对应的pushByte()实例都需要更改为pushShort(),类似于popByte()popShort() 。重载pop()push()以解决此问题会导致类型冲突(导致显式转换,最终导致同样的问题)。

通过上述想法,我可以创建一个工人阶级。但是,我想知道如何编译专用模板。如果我创建了push<byte>()push<short>(),那么它将是特定于类型的重载,并且从字节到短的更改会自动切换所使用的模板,这将是理想的。

现在,我的问题是,如果我只使用专门的模板来模拟这种重载(没有T类型的模板),那么所有特化都会编译到我的DLL中,允许我在没有客户端的情况下调度新的实现重新编译?或者是在客户端编译时以与T类型的模板相同的方式选择或删除专用模板?

2 个答案:

答案 0 :(得分:2)

首先,您不能拥有专门的模板而没有专门的基本模板。这是不允许的。您必须从模板开始,然后您可以提供它的特化。

您可以在任意类型的集合上显式实例化模板,并将所有这些实例编译到您的DLL中,但我不确定这对您来说真的会有很大帮助。最终,模板基本上是多态的编译时形式,并且您似乎需要(至少是有限形式的)运行时多态性。

我可能只是使用重载。我猜你正在谈论的问题出现在以下的顺序:

int a;
byte b;

a = pop();
b = pop();

你基本上只是在返回类型上重载pop(我们都知道,这是不允许的)。我会避免这么简单 - 不是返回值,而是传递对要修改的值的引用:

int a;
byte b;

pop(a);
pop(b);

这不仅可以让重载解析工作,但至少对我来说看起来更干净(虽然我可能只是写了太多的汇编语言,所以我习惯于像“pop ax”这样的东西)。

答案 1 :(得分:1)

听起来你有两个相反的因素:

  1. 您希望您的客户能够推/弹/等。每种数字类型。模板似乎是一个自然的解决方案,但这与一致(只需编译一次)实现不一致。
  2. 您不希望客户在更改实施方面时必须重新编译。 pimpl idiom似乎是一种自然的解决方案,但这与通用(适用于任何类型)实现不一致。
  3. 从你的描述来看,听起来你只关心数字类型,而不是任意的T。您可以在头文件中明确声明每个模板的特化,并在源文件中定义它们,客户端将使用您定义的特化而不是编译它们自己的特化。专业化是编译时多态的一种形式。现在,您可以将其与运行时多态性结合使用 - 根据类型不可知的实现类实现特化。您的实现类可以使用boost::variant来执行此操作,因为您可以提前了解可能的T的范围(boost::variant<int, short, long, ...>)。如果提升不是你的选择,你可以自己想出一个类似的方案,只要你有一个有限的你关心的Ts。

相关问题