sxs-collaboration / spectre

SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
https://spectre-code.org
Other
154 stars 187 forks source link

Streaming nested STL containers doesn't work #2480

Open wthrowe opened 3 years ago

wthrowe commented 3 years ago
#include <array>
#include <iostream>
#include <vector>

#include "Utilities/StdHelpers.hpp"

void f() {
  // std::vector<int> x{};  // fine                                             
  // std::array<int, 1> x{};  // fine                                           
  std::vector<std::array<int, 1>> x{};  // error
  std::cout << x;
}
/home/wthrowe/spectre/src/Utilities/PrintHelpers.hpp:42:63: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
      [](std::ostream& os, const ForwardIt& it) noexcept { os << *it; });
                                                              ^
/home/wthrowe/spectre/src/Utilities/StdHelpers.hpp:81:3: note: in instantiation of function template specialization 'sequence_print_helper<__gnu_cxx::__normal_iterator<const std::array<int, 1> *, std::vector<std::array<int, 1>, std::allocator<std::array<int, 1> > > > >' requested here
  sequence_print_helper(os, std::begin(v), std::end(v));
  ^
nilsdeppe commented 3 years ago

I think the fix is adding a using ::operator<<; inside those lambdas that do the streaming. Would you be willing to try that?

wthrowe commented 3 years ago

I get "error: no member named 'operator<<' in the global namespace".

I've noticed that the code is sensitive to the order of includes. In my original code snippet, including "Utilities/StlStreamDeclarations.hpp" before "Utilities/StdHelpers.hpp" makes everything work, but including it after does not help.

nilsdeppe commented 3 years ago

Sorry for the delay... Yea, I can see why this would be include order dependent... I don't really have a great idea other than the super sketchy (and technically UB) of moving the operator<< for STL containers into the std namespace. I'll need to think more about it. Maybe we can convince ADL to delay lookup long enough that all includes have been parsed?

wthrowe commented 3 years ago

It seems like this can mostly be worked around using MakeString (and probably get_output). Catch provides a way to override its "{?}" output using a CATCH_CONFIG_FALLBACK_STRINGIFIER, but I haven't found a way to make it work yet.

nilsdeppe commented 3 years ago

That sounds like a much better approach :) It's nice that catch has a stringifier (as long is it works :P )