当我编写一个类似于字符串的通用模板类时,我遇到了一个两难问题,它给出了一个代表我使用的常见数据结构的QString。我希望我可以在此头文件(#include in .h or .c / .cpp?)中包含最少数量的其他头文件,但也希望它不依赖于它包含的顺序(Header file order)。
基本代码是这样的:
// Some headers
template <typename T>
class PMsg
{
// Public routines
public:
static QString fromType();
static QString fromValue(T const &val);
}; // PMsg
// Inline definition of all methods in PMsg<T>::fromValue
// Some specialisation
// To be continued...
以下是问题:容器类。我是否应该执行以下操作来拉动所有容器标头以使其正常工作:
// To the beginning
#include <QtCore/QList>
#include <QtCore/QVector>
// After PMsg<T>
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
或者使用宏来检测包含的标题:
#if defined(QLIST_H)
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
#endif
#if defined(QVECTOR_H)
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
#endif
我可能最终会包含20多个不同的标题(包括像Eigen那样的非Qt类),或者我可能依赖Qt可以更改的内容,而不会告诉下游开发人员并要求我的同事在此标题之前包含Qt标题肯定的。
我也不确定此时两种方式对编译时间的影响有多大(如果我没有解决这个问题,可能不应该考虑)。
还有其他更好的方法可以解决这个问题,或者我应该遵循哪种方式?
对不起的问题标题表示歉心,感谢您的帮助。
答案 0 :(得分:2)
根据您的说明,您提供的组件具有自定义点(PMsg<T>
),可用于添加的组件。您似乎还希望拥有一组已知的组件来利用此自定义。这导致以下推理:
"pmsg.h"
)。"pmsg.h"
中自定义这些组件。QVector<T>
)不了解此自定义,并且无法与您的组件集成,需要在"pmsg.h"
中声明其自定义。如果不在"pmsg.h"
中声明自定义,则除了现有组件的标头之外,所有用户都需要记住还包括声明自定义的标头。假设有一个默认的自定义实现,那不仅会产生意外结果,而且当不同的翻译单元与它们包含的标题不一致时,很容易导致ODR违规。"pmsg.h"
中转发声明组件以声明自定义,然后在源文件中实现声明,而不实现"pmsg.h"
中的声明。也就是说,对于定制的非模板组件,不需要在声明中包含相应的标题,声明就足够了。"pmsg.h"
中为模板化自定义提供定义。也就是说,您需要在"pmsg.h"
中包含您想要/需要自定义的所有模板类的声明。tl; dr:如果您想为现有组件提供自定义,您需要在标题中声明它们,并且这样做,您也需要包括它们各自的声明。