There is no op<< for std::map. The universal printing example requires one.
Trouble is, Boost.Describe seems to require it in the std namespace, except of course that's illegal to add to std,
except for specializations. (I'm no expect, but I know that one). I cannot share the exact code that fails for me,
since it's part of a large code-generated library, but essentially it boils down to what's below.
With it's illegal op<< for the instantiated map template for <string, My::Inner>, this builds fine on MSVC 2019, C++17.
I did not even try providing a templated one, to simply my testing.
I realize it's not the best of report, but hopefully you can see the big picture, and perhaps even prove me wrong via a simple example.
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/test/unit_test.hpp>
#include <ostream>
#include <sstream>
namespace My {
struct PseudoVariant { // not described
int idx_;
std::any val_;
// idx() getter, bunch of set_Xyz and get_Xyz() typed accessor to val_'s allowed content...
};
struct Inner { // described
PseudoVariant item_;
};
struct Outer { // described
std::map<std::string, Inner> inners_;
// other fields
};
// Dummy op<<(PseudoVariant) for test_2level_struct() specifically, printing just ints, not the other types
std::ostream& operator<<(std::ostream& os, const PseudoVariant & dv_item) {
return os
<< "{" << "#" << dv_item.idx() << "="
<< ((dv_item.idx() == 2)? dv_item.get_int(): -1) << "}"
;
}
} // My
namespace std {
std::ostream& operator<<(std::ostream& os, const std::map<std::string, My::Inner>& map) {
return os << My::to_string(map); // implemented elsewhere
}
} // std
namespace describe_utils {
using namespace boost::describe;
std::ostream& operator<<(std::ostream& os, const T& t) {
os << '{';
bool first = true;
boost::mp11::mp_for_each<Bd>(
[&](auto D) {
if (!first) {
os << ", ";
}
first = false;
using B = typename decltype(D)::type;
os << (B const&)t;
}
);
boost::mp11::mp_for_each<Md>(
[&](auto D) {
if (!first ) {
os << ", ";
}
first = false;
os << '.' << D.name << " = " << t.*D.pointer;
}
);
return os << '}';
}
} // namespace describe_utils
namespace {
template <typename T>
std::string as_string(const T& t) {
using namespace describe_utils;
std::ostringstream oss;
oss << t;
return oss.str();
}
BOOST_AUTO_TEST_SUITE(DescribeTests)
BOOST_AUTO_TEST_CASE(test_2level_struct) {
using namespace describe_utils;
using namespace My;
Outer o;
// fill o
std::string sps = as_string(sp);
}
BOOST_AUTO_TEST_SUITE_END()
} // End anonymous namespace
Here's the error I get, if not using that illegal std op<<.
I put it in a different namespace, like the local anon one, or another in-scope, similar error each time.
1>------ Build started: Project: tests_describe, Configuration: Debug x64 ------
1>DescribeTests.cpp
1>D:\dev\src\tests\misc\DescribeTests.cpp(104,1): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'const std::map<std::string,My::Inner,std::less<std::string>,std::allocator<std::pair<const std::string,My::Inner>>>' (or there is no acceptable conversion)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(466,39): message : could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(441,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(423,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long double)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(405,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(double)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(387,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(float)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(369,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned __int64)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(351,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(__int64)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(333,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned long)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(315,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(296,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned int)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(270,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(251,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned short)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(217,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(short)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(199,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(bool)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(194,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::ios_base &(__cdecl *)(std::ios_base &))'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(189,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ios<char,std::char_traits<char>> &(__cdecl *)(std::basic_ios<char,std::char_traits<char>> &))'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(184,39): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ostream<char,std::char_traits<char>> &(__cdecl *)(std::basic_ostream<char,std::char_traits<char>> &))'
1>D:\dev\src\tests\misc\DescribeTests.cpp(31,15): message : or 'std::ostream &My::operator <<(std::ostream &,const My::PSeudoVariant &)' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(461,20): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<<void>(std::nullptr_t)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(654,32): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(698,32): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(734,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(779,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(896,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const signed char *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(902,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,signed char)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(907,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const unsigned char *)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(913,31): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,unsigned char)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\ostream(1001,32): message : or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const std::error_code &)'
1>D:\dev\src\tests\misc\DescribeTests.cpp(104,1): message : while trying to match the argument list '(std::basic_ostream<char,std::char_traits<char>>, const std::map<std::string,My::Inner,std::less<std::string>,std::allocator<std::pair<const std::string,My::Inner>>>)'
1>D:\pdgm\kits\trunk\boost\1.74.0\Win_x64_10_v16_debug\include\boost/mp11/algorithm.hpp(1037): message : see reference to function template instantiation 'auto describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b>::operator ()<boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>>(boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>) const' being compiled
1>D:\pdgm\kits\trunk\boost\1.74.0\Win_x64_10_v16_debug\include\boost/mp11/algorithm.hpp(1055): message : see reference to function template instantiation 'F boost::mp11::detail::mp_for_each_impl<boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_88c58abe40ddca9e64b2955f6dbfa7ea>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_5916e84125bc784d483539ad1d3a3d09>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_c9d2335107088328dfd07a87925d597b>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>,_Ty>(boost::mp11::mp_list<boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_88c58abe40ddca9e64b2955f6dbfa7ea>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_5916e84125bc784d483539ad1d3a3d09>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_c9d2335107088328dfd07a87925d597b>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>>,F &&)' being compiled
1> with
1> [
1> F=describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b>,
1> _Ty=describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b>
1> ]
1>D:\dev\src\tests\misc\DescribeTests.cpp(106): message : see reference to function template instantiation 'describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b> boost::mp11::mp_for_each<Md,describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b>>(F &&)' being compiled
1> with
1> [
1> Md=boost::describe::detail::list<boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_88c58abe40ddca9e64b2955f6dbfa7ea>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_5916e84125bc784d483539ad1d3a3d09>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_c9d2335107088328dfd07a87925d597b>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>>,
1> F=describe_utils::<<::<lambda_734585ecef8cae37a0607e5d54dd865b>
1> ]
1>D:\dev\src\tests\misc\DescribeTests.cpp(118): message : see reference to function template instantiation 'std::ostream &describe_utils::operator <<<T,boost::describe::detail::list<>,boost::describe::detail::list<boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_88c58abe40ddca9e64b2955f6dbfa7ea>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_5916e84125bc784d483539ad1d3a3d09>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_c9d2335107088328dfd07a87925d597b>::()::D,1>,boost::describe::detail::member_descriptor<My::_public_member_descriptor_fn::<lambda_bab1101c997e04563d84b2536558ac70>::()::D,1>>>(std::ostream &,const T &)' being compiled
1> with
1> [
1> T=My::Outer
1> ]
1>D:\dev\src\tests\misc\DescribeTests.cpp(200): message : see reference to function template instantiation 'std::string `anonymous-namespace'::as_string<My::Outer>(const T &)' being compiled
1> with
1> [
1> T=My::Outer
1> ]
1>Done building project "tests_describe.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========