未使用 CPPUnit 的模板专业化
如果您以前使用过 CPPUnit,您可能知道它的 assertion_traits
类已模板化以处理任意类型。这使得它可以在测试用例失败时打印非字符串类型的“实际”和“预期”值。我已经成功使用过几次,但对于一种特定类型,它对我不起作用。这是我的类、其父类和一些非成员运算符的部分声明(整个事情很大,而且我的公司不允许我发布它):
class _declspec(dllexport) HWDBDateTime
{
public:
HWDBDateTime();
HWDBDateTime(const HWDBDateTime& other);
HWDBDateTime& operator=(const HWDBDateTime& other);
RWCString asString() const;
RWCString asString(const char *format, const boost::local_time::time_zone_ptr pZone = STimeZone::GetServerTimeZone()) const;
};
bool _declspec(dllexport) operator==(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator!=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator< (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator<=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator> (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator>=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
class _declspec(dllexport) STimeStamp : public HWDBDateTime
{
public:
STimeStamp();
STimeStamp(const STimeStamp& other);
STimeStamp(const HWDBDateTime& other);
explicit STimeStamp(double d);
STimeStamp& operator=(double d);
operator double() const;
};
这是我对 CPPUnit 断言类进行专门化的尝试:
template <>
struct CppUnit::assertion_traits<STimeStamp>
{
static bool equal( STimeStamp x, STimeStamp y )
{
return x == y;
}
static std::string toString( STimeStamp x )
{
return (const char *)x.asString();
}
};
我尝试过按值传递,如上所示,还传递 const 引用,我尝试将函数内的值转换为 HWDBDateTime (因为这就是运算符和 asString() 的位置) 方法已定义),似乎没有任何帮助。我将其放在测试套件的 CPP 文件的顶部,并将其放入包含项目范围的assertion_traits 专业化的主头文件中,例如完美运行的 RWCString 头文件。不知何故,每当测试用例失败时,它都会坚持将我的时间打印为浮点值(大概是双精度值;CPPUnit 中内置了双精度值的专门化)——这就是为什么我确保包含我的 to/from上面最小化代码中的双重转换运算符。
我所做的事情是否存在本质上的错误?专业化是否需要在编译过程中的某个点出现,也许我只是还没有找到那个点?这个神话点是针对每个翻译单元还是针对每个项目?我用的是VS2008。
If you've used CPPUnit before, you are probably aware of its assertion_traits
class that is templatized to handle arbitrary types. This is what allows it to print the "actual" and "expected" values for non-string types when test cases fail. I have used this with success several times, but for one specific type it isn't working for me. Here is a partial declaration for my class, its parent's class, and some non-member operators (the whole thing is huge, plus my company won't let me post it):
class _declspec(dllexport) HWDBDateTime
{
public:
HWDBDateTime();
HWDBDateTime(const HWDBDateTime& other);
HWDBDateTime& operator=(const HWDBDateTime& other);
RWCString asString() const;
RWCString asString(const char *format, const boost::local_time::time_zone_ptr pZone = STimeZone::GetServerTimeZone()) const;
};
bool _declspec(dllexport) operator==(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator!=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator< (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator<=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator> (const HWDBDateTime& dt1, const HWDBDateTime& dt2);
bool _declspec(dllexport) operator>=(const HWDBDateTime& dt1, const HWDBDateTime& dt2);
class _declspec(dllexport) STimeStamp : public HWDBDateTime
{
public:
STimeStamp();
STimeStamp(const STimeStamp& other);
STimeStamp(const HWDBDateTime& other);
explicit STimeStamp(double d);
STimeStamp& operator=(double d);
operator double() const;
};
And here is my attempt at specializing the CPPUnit assertions class:
template <>
struct CppUnit::assertion_traits<STimeStamp>
{
static bool equal( STimeStamp x, STimeStamp y )
{
return x == y;
}
static std::string toString( STimeStamp x )
{
return (const char *)x.asString();
}
};
I've tried it passing by value, as seen above, also passing const references, I've tried casting the values inside the functions to HWDBDateTime
(since that's where the operators and asString()
methods are defined), nothing seems to help. I've put it at the top of my test suite's CPP file, and I've put it into a master header file that contains project-wide assertion_traits specializations, such as one for RWCString that works flawlessly. Somehow, whenever a test case fails, it insists on printing out my time as a floating-point value (presumably a double; a specialization for double is built in to CPPUnit) -- this is why I made sure to include my to/from double conversion operators in the minimized code above.
Is there something inherently wrong with what I'm doing? Does the specialization need to be present at a certain point in the compilation process, and maybe I just haven't found that point? Would this mythical point be per-translation-unit or per-project? I'm using VS2008.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C++ 类型匹配是这里的问题。
原始类型可能是 const STimeStamp& 。当来自 const T& 时,大多数编译器更喜欢隐式转换运算符(在您的情况下是
double
),而不是创建副本T
。这可能是编译器特定的......
C++ type matching is the issue here.
The original type is probably
const STimeStamp&
. When coming fromconst T&
most compilers prefers the implicit cast operators (in your casedouble
) over creating a copyT
.This may be compiler specific...