2009-09-22 99 views
1

我正在使用CPPUnit在我的程序中测试一个类。这个类(SCriterionVal)有点独特,因为它有许多类型的转换运算符(它本质上是一个动态类型值类)。当我编译使用CPPUNIT_ASSERT_EQUAL()进行测试的测试用例时,我从其中一个CPPUnit头文件中收到关于“operator<<不明确”的编译错误。看来它正在用我的类型实例化assertion_traits结构,并且该结构有一个toString()方法,该方法在OStringStream上使用operator<<工作。超载运算符<<用于ostream

由于SCriterionVal可用的各种转换(其中一些定义了operator<<(如内置类型)),我们假设它是模糊的而不是错误。在试图改变这种状况,我创造了一个头非成员函数SCriterionVal与此签名:

ostream &operator<<(ostream &stream, SCriterionVal val); 

我想通因为签名应该是完全匹配的,它会解决歧义。没有这样的运气。我在这里做错了什么?我想我可以专门为我的类型设计assertion_traits的模板,但我希望能够解决更普遍的问题,即提供一种方法将我的类放入流中,而不仅仅是迎合测试框架。

+1

英文描述是SOOO比代码好得多的另一种情况。 – 2009-09-22 18:48:45

+1

我想我们应该创建另一个标签EBTC(英文是更好然后代码) – 2009-09-22 18:50:04

+0

马丁,我认为你的意见是讽刺。我无法发布代码,因为这违反了我公司的政策。此外,它是一个非常大的类,并使用数十种自定义类型,因此无论如何您都无法编译它。 – rmeador 2009-09-22 19:01:55

回答

2

尝试将operator<<定义为类定义中的朋友内联函数。我总是发现这种方式最好,特别是对于模板。

例如,Boost.Random定义operator<<exponential distribution的声明中:

template<class CharT, class Traits> 
    friend std::basic_ostream<CharT,Traits>& 
    operator<<(std::basic_ostream<CharT,Traits>& os, const exponential_distribution& ed) 
    { 
    os << ed._lambda; 
    return os; 
    } 
+0

这是一个我从未见过的有趣技术。该函数实际上是一个方法,还是它仍然是一个函数不附加到一个对象(我不知道这个术语)?我正在编辑现在的变化,所以我会让你知道它是怎么回事...... – rmeador 2009-09-22 19:11:08

+0

@meador:'friend'可以接受函数定义而不是声明。这可能看起来很奇怪(这对我来说确实如此),但这就是它的方式。定义的函数仍然是一个自由函数,即使它是在类中定义的。 – sbi 2009-09-22 20:06:09

+0

我试着用你的模板化basic_ostream返回类型,它抱怨说我的函数是一个返回值的void函数。我猜这与我的编译器是MSVC++ 6这一事实有关。我用“ostream”而不是模板重新编写了它,并且仍然得到了我原来的模糊性错误。我放弃了...我会给你一个+1,假设你的答案会帮助有合理编译器的人。 – rmeador 2009-09-22 20:33:35