【问题标题】:How to keep code clean with template classes?如何使用模板类保持代码干净?
【发布时间】:2014-11-23 00:03:18
【问题描述】:

我有一个这样的模板类:

template <class TType> class Class1;

这个类被用于许多其他类:

class Class2 {
    Class1 _class1;    // How to pass the template parameter of Class1 in a clean way ?
};

// Same for Class3, Class4, ...

问题是Class1的模板参数必须由客户端代码选择,所以我不能直接这样说:

class Class2 {
    Class1<OneType> _class1;    // Not correct, template parameter must be chosen by client code
};

所以正确的方法是将 Class2 也设置为模板类:

template <class TTypeClass1> class Class2 {
    Class1<TTypeClass1> _class1;
};

这种技术的问题是所有使用Class1的类都必须是模板类,所以我们污染了其他类的代码来传递Class1的模板参数,如果这些类是由许多模板类和许多模板组成的,那就更糟了参数。

我发现了另一种我认为更清洁的方法:

template <class TTypeClass1 /* And possible other parameters */> struct ClientConfiguration {
    // Declaration of EntityManager
    typedef Class1<TTypeClass1> Class1Typed;
};

// Configuration defined by client code
typedef ClientConfiguration<OneTypeForClass1 /* And possible other parameters */> CurrentClientConfiguration;

class Class2 {
    CurrentClientConfiguration::Class1Typed _class1;
}

但是有没有更好的方法来做到这一点?

【问题讨论】:

  • “但是有没有更好的方法来做到这一点?” 更好的方法和要求是什么?为什么在这里引入可变参数模板参数?请您稍微澄清一下您的问题。
  • 您的ClientConfiguration 不会按您希望的方式工作。您似乎假设在同一个程序中可以有不同的Class2“实例化”,根据CurrentClientConfiguration::Class1Typed 的不同定义编译。如果您真的尝试这样做,您的程序将违反一个定义规则,因此会表现出未定义的行为。
  • 您的库代码具有任何模板代码的所有常见缺点,即它必须作为头文件提供并由用户编译,但没有普通模板代码的清晰和明确性。 Class2 取决于用户提供的定义,您可以仅通过查看它来确认或否认吗?另外,您打算如何实现这个// Configuration defined by client code 位?通过#include 输入一个文件,比如usercode.h 并让用户提供一个文件?如果是这种情况,您可以完全省略模板,只需让用户创建一些 typedef。
  • 我不确定我是否在这里看到了需要解决的问题。如果类A 引用参数化类型B,则A 本身必须是参数化的。否则,您可以(并且应该)在其对B 的引用中硬编码类型参数。如果必须对A 进行参数化,为什么要跨越障碍去尝试找到一种更模糊的表达方式呢?诚然,带有模板的 C++ 编译模型使这种传播有些痛苦,但这些就是你所拥有的语义,这就是你在 C++ 中表达这些语义的方式。
  • template 类型参数是某些代码的编译时参数。为什么选择编译时参数而不是运行时?如果“性能”,您是否证明这是一个瓶颈,或者只是假设并喷出代码?如果您已经证明它是一个瓶颈,那么该选择是否可以被类型擦除?即,您能否抽象出对运行时接口的性能至关重要的部分,然后从其他地方注入该选择?

标签: c++ class templates c++11


【解决方案1】:

我的第一个想法是推荐 Class1 从抽象基类继承,然后构造 Class2 (等等),例如,使用工厂来制作您(或客户)想要的 Class1 的味道。

但是,我认为在这个特定问题中你似乎追求的更好的引导可能是使用特征?

struct TTrait_int {
    typedef int TClass1;
};
struct TTrait_float {
    typedef float TClass1;
};
template <class TRAITS>
class Class2 {
    Class1<typename TRAITS::TClass1> _class1;
};
...
Class2<TTrait_int> c2tta;
Class2<TTrait_float> c2ttb;

明确地说,这在简单的 1 模板参数情况下没有真正的好处。

但它确实可以很好地扩展非常...

您只需要一个 Class2 模板参数 - 特征类:而不是不断增长的 Class2 模板参数列表,而是增加该特征类必须提供的“名称”套件。

(如果您想丢失 Class2 上的单个模板参数...请参阅我的第一句话。)

【讨论】:

    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多