0

in my code I overloaded the stream operator for a class ByteArray (which is simply a vector of bytes).

// myfile.hpp
using ByteArray_t = std::vector<uint8_t>;

std::ostream &operator<<(std::ostream &os, const ByteArray_t &array);
...

// myfile.cpp
std::ostream &operator<<(std::ostream &os, const ByteArray_t &array) {... return os;}

and a test.cpp using Catch2 which uses this class

TEST_CASE("Oh-my", "[...]") {
  ByteArray_t frame = create(max_val); // write the bytes of max val into the array

  INFO(frame); // Print frame if test fails (uses '<<' operator)

  REQUIRE(...);
}

This worked fine unless I introduced a namespace


namespace mw {
// myfile.hpp
using ByteArray_t = std::vector<uint8_t>;

std::ostream &operator<<(std::ostream &os, const ByteArray_t &array);
} // namespace mw
...

// myfile.cpp
namespace mw {
std::ostream &operator<<(std::ostream &os, const ByteArray_t &array) {... return os;}
}  // namespace mw

Now the compiler complains

 error: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'const std::vector<unsigned char, std::allocator<unsigned char> >')
            *m_oss << value;
            ~~~~~~ ^  ~~~~~
.../include/catch2/catch.hpp:2629:22: note: in instantiation of function template specialization 'Catch::ReusableStringStream::operator<<<std::vector<unsigned char, std::allocator<unsigned char> > >' requested here
            m_stream << value;
tests.cpp:69:15: note: in instantiation of function template specialization 'Catch::MessageBuilder::operator<<<std::vector<unsigned char, std::allocator<unsigned char> > >' requested here
  **INFO(frame);**

However, if I use frame with std::cout, this works fine

  INFO(frame);                // <== Compiler error
  std::cout << frame << '\n'; // <== OK

So I think, that the compiler can resolve the operator properly. I tried also to change the sequence of include files and a clean rebuild - without success.

Any ideas? Thanks

Oliver
  • 1
  • 1
    How does catch2 know to use the namespace `mw` to resolve your overload? I believe you should place that either in the global namespace, or add an adequate `using` statement into your test module. – πάντα ῥεῖ Apr 05 '21 at 15:25
  • > *However, if I use frame with std::cout, this works fine* - Cannot reproduce: https://godbolt.org/z/EG43b3fzW Where did you do the the `std::cout`? In your own namespace? – ph3rin Apr 05 '21 at 15:39

1 Answers1

0

@Meowmere: Yes, your suggested answer solved the problem - thanks

The solution was to use a derived class instead of an alias.

using ByteArray_t = std::vector<uint8_t>; // does **NOT** work
struct ByteArray_t :public std::vector<uint8_t> {}; // works
Oliver
  • 1