views:

280

answers:

1

I am using CPPUnit to test a class in my program. This class (SCriterionVal) is somewhat unique because it has conversion operators for a lot of types (it's essentially a dynamic type value class). When I compile test cases that test it using CPPUNIT_ASSERT_EQUAL(), I get compilation errors about "operator<< is ambiguous" from one of the CPPUnit header files. It appears that it is instantiating the assertion_traits struct with my type, and that struct has a toString() method that works by using operator<< on an OStringStream.

I assume it's ambiguous instead of an error because of the various conversions available on SCriterionVal, some of which have defined operator<< (such as the built in types). In an attempt to rectify this situation, I created a non-member function in the header for SCriterionVal with this signature:

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

I figured because the signature should be an exact match, it will resolve the ambiguity. No such luck. What am I doing wrong here? I suppose I can specialize the template for assertion_traits for my type, but I was hoping to be able to solve the more general problem of providing a way to put my class into a stream, rather than just catering to the test framework.

+2  A: 

Try defining operator<< as a friend inline function inside the class definition. I always find this way works the best, especially for templates.

For example, Boost.Random defines operator<< inside exponential distribution's declaration:

  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;
  }
rlbond
this is an interesting technique I haven't seen before. Is the function actually a method, or is it still a function not attached to an object (I don't know a term for that)? I'm compiling with the changes now, so I'll let you know how it goes...
rmeador
@meador: The `friend` can take a function definition instead of a declaration. That might seem strange (it certainly does to me), but that's just the way it is. The defined function is still a free function, even though it's defined inside the class.
sbi
I tried it with your templatized basic_ostream return type and it complained that my function was a void function returning a value. I'm guessing that has to do with the fact that my compiler is MSVC++ 6. I recoded it with just "ostream" instead of the template and I still get the ambiguity error I originally had. I'm giving up... I'll give you a +1 under the assumption that your answer will help someone with a reasonable compiler.
rmeador
MSVC++6 would be why it doesn't work. It doesn't support template overload resolution very well, so you are probably encountering the simple problem that the compiler sucks.
coppro