不使用模板参数的模板类

时间:2014-04-16 09:15:26

标签: c++ templates software-design

我曾多次在类似

的课程上跌跌撞撞
class PureVirtualClass
{
   virtual int foo() = 0;
   virtual bool bar() = 0;
}

template <class T> class ImplClass : public virtual PureVirtualClass
{
   virtual ~ImplClass(){};
   int foo()  { return 42;}
   bool bar() { return true;}
   //several other method having nothing to do with T
}

这个&#34;设计&#34;经常出现我想通过将ImplClass定义为模板类但没有任何引用到模板参数T 任何地方< / em>的。我自己的c ++模板知识有点受限。

这有什么好处,还是只是一个混乱的程序员?

3 个答案:

答案 0 :(得分:3)

可以对模板化的类有益,但不依赖于参数。大多数情况下,你会看到为模板元编程定义(空)标签结构的事情:

template <class X>
struct some_tag {};

像你这样的类的好处一般是,虽然你在每个类中具有相同的功能,但它们是不同的类,你不能将一个复制到另一个类,即ImplClass<int>类型的对象与ImplCalss<float>类型的另一个对象不兼容。

答案 1 :(得分:3)

Arne提到的这个想法有很多有用的案例。例如,查看Very basic tuple implementation,这就是如何定义单个元组元素:

template <size_t N, typename T>
class TupleElem
{
    T elem;
public:
    T&       get()       { return elem; }
    const T& get() const { return elem; }
};

它是N的模板,不依赖于它。为什么?因为元组实现

template <size_t... N, typename... T>
class TupleImpl <sizes <N...>, T...> : TupleElem <N, T>...
{
    //..
};

派生多个此类元素,每个元素都有一个唯一的N,用作标识符。没有它,TupleImpl将两次派生相同的类,在参数包T...中有两个元素类型相同。在这种情况下,random access元素都不会起作用(通过显式调用适当的get()基类的函数TupleElem,这将是不明确的),也不是empty base optimization(通过专门针对空类型TupleElem的{​​{1}}到而非T数据成员{。}}。

这是一个真实的用例,以及clang实现T的确切方式。当然,像std::tuple这样的类将是隐藏的实现细节,而不是接口的一部分。例如,gcc遵循完全不同的递归类设计。

通常,您需要学习 context ,其中使用类来理解设计者的意图。

答案 2 :(得分:1)

也许开发人员懒得将类拆分成.h和.cpp文件?

如果在多个编译单元中使用类,则不使用模板会发生链接器错误。使用模板时,链接器通常会在链接时丢弃模板的重复实例化(或以不同方式处理问题)。

虽然这可能是“为什么开发人员这样做”的答案,但如果问题是“何时应该引入从未使用的模板参数”,我不建议这样做(请参阅其他答案)。即使将代码拆分为.h和.cpp(特别是在用于Java或C#等语言时)也很烦人,但这是通常的C ++方式。与仅为此目的使用模板相比,它更容易阅读/理解。此外,它使类的使用更不易读。