Variant stream output of ICU UnicodeString

Hi, I'm trying to stream a Boost::Variant with << to std::cout but when I include an UnicodeString member from the ICU Unicode library the compiler doesn't recognices my overloaded operator<< for the UnicodeString. Here is a test program: #include <iostream> #include <unicode/unistr.h> #include <boost/variant.hpp> class Foo {}; std::ostream& operator<<(std::ostream& stream, Foo const &b) { return stream << "Foo"; } std::ostream& operator<<(std::ostream& stream, UnicodeString const & unicode) { return stream << "Unicode"; } int main() { boost::variant<Foo, UnicodeString, int, double> test; test = Foo(); std::cout << test << std::endl; test = "Hello World"; std::cout << test << std::endl; return 0; } Without the UnicodeString code everything works find but with it I get the following errors: g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/TestUnicode.d" -MT"src/TestUnicode.d" -o "src/TestUnicode.o" "../src/TestUnicode.cpp" In file included from /usr/include/boost/variant/variant.hpp:1859, from /usr/include/boost/variant.hpp:17, from ../src/TestUnicode.cpp:11: /usr/include/boost/variant/detail/variant_io.hpp: In member function ‘void boost::detail::variant::printer<OStream>::operator()(const T&) const [with T = icu_4_2::UnicodeString, OStream = std::basic_ostream<char, std::char_traits<char> >]’: /usr/include/boost/variant/variant.hpp:825: instantiated from ‘typename Visitor::result_type boost::detail::variant::invoke_visitor<Visitor>::internal_visit(T&, int) [with T = const icu_4_2::UnicodeString, Visitor = boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > >]’ /usr/include/boost/variant/detail/visitation_impl.hpp:126: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl_invoke_impl(int, Visitor&, VoidPtrCV, T*, mpl_::true_) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T = boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_which, step0 = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_step, Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, NoBackupFlag = boost::variant<Foo, icu_4_2::UnicodeString, int, double, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_]::T1]’ /usr/include/boost/variant/detail/visitation_impl.hpp:169: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl_invoke(int, Visitor&, VoidPtrCV, T*, NoBackupFlag, int) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T = boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_which, step0 = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_step, Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, NoBackupFlag = boost::variant<Foo, icu_4_2::UnicodeString, int, double, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_]::T1, NoBackupFlag = boost::variant<Foo, icu_4_2::UnicodeString, int, double, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_]’ /usr/include/boost/variant/detail/visitation_impl.hpp:256: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_which, step0 = boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]::first_step, Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, NoBackupFlag = boost::variant<Foo, icu_4_2::UnicodeString, int, double, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_]’ /usr/include/boost/variant/variant.hpp:1769: instantiated from ‘static typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, VoidPtrCV = const void*, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]’ /usr/include/boost/variant/variant.hpp:1791: instantiated from ‘typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor(Visitor&) const [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > > >, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]’ /usr/include/boost/variant/variant.hpp:1813: instantiated from ‘typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::apply_visitor(Visitor&) const [with Visitor = boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > >, T0_ = Foo, T1 = icu_4_2::UnicodeString, T2 = int, T3 = double, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]’ /usr/include/boost/variant/detail/variant_io.hpp:85: instantiated from ‘std::basic_ostream<_CharT, _Traits>& boost::operator<<(std::basic_ostream<_CharT, _Traits>&, const boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&) [with E = char, T = std::char_traits<char>, U0 = Foo, U1 = icu_4_2::UnicodeString, U2 = int, U3 = double, U4 = boost::detail::variant::void_, U5 = boost::detail::variant::void_, U6 = boost::detail::variant::void_, U7 = boost::detail::variant::void_, U8 = boost::detail::variant::void_, U9 = boost::detail::variant::void_, U10 = boost::detail::variant::void_, U11 = boost::detail::variant::void_, U12 = boost::detail::variant::void_, U13 = boost::detail::variant::void_, U14 = boost::detail::variant::void_, U15 = boost::detail::variant::void_, U16 = boost::detail::variant::void_, U17 = boost::detail::variant::void_, U18 = boost::detail::variant::void_, U19 = boost::detail::variant::void_]’ ../src/TestUnicode.cpp:27: instantiated from here /usr/include/boost/variant/detail/variant_io.hpp:64: error: no match for ‘operator<<’ in ‘((const boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> >
*)this)->boost::detail::variant::printer<std::basic_ostream<char, std::char_traits<char> > >::out_ << operand’ /usr/include/c++/4.4/ostream:108: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:117: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:127: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:165: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/bits/ostream.tcc:91: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:180: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/bits/ostream.tcc:105: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:191: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:200: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:209: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:221: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.4/bits/ostream.tcc:119: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]
I'm using gcc 4.4.5 on Ubuntu 11.04 and boost 1.42. Does someone know why the overloaded operator isn't used or how I can get the test program to work?

On Sun, 09 Oct 2011 06:53:22 -0700, André <andre@onlinehome.de> wrote:
Hi, I'm trying to stream a Boost::Variant with << to std::cout but when I include an UnicodeString member from the ICU Unicode library the compiler doesn't recognices my overloaded operator<< for the UnicodeString.
Here is a test program:
<snip>
I'm using gcc 4.4.5 on Ubuntu 11.04 and boost 1.42. Does someone know why the overloaded operator isn't used or how I can get the test program to work?
Keeping in mind that UnicodeString is defined in namespace icu_<some-version-number>, what you've pointed out is not limited to UnicodeString. The following simplified example apparently shows ADL failing for Boost.Variant when the streaming operator for Foo is defined in the global namespace instead of Foo's defining namespace. (gcc 4.0.1, boost 1.4.5) #include <iostream> #include <boost/variant.hpp> namespace Bar { struct Foo {}; } std::ostream& operator<<(std::ostream& stream, Bar::Foo const &b) { return stream << "Foo"; } int main() { //Not compiles. boost::variant<Bar::Foo, char const *, int, double> test; //Compiles. //Bar::Foo test; test = Bar::Foo(); std::cout << test << std::endl; return 0; } Is this a bug in Boost.Variant? Mostafa

On Oct 9, 2011, at 3:12 PM, Mostafa <mostafa_working_away@yahoo.com> wrote:
On Sun, 09 Oct 2011 06:53:22 -0700, André <andre@onlinehome.de> wrote:
Hi, I'm trying to stream a Boost::Variant with << to std::cout but when I include an UnicodeString member from the ICU Unicode library the compiler doesn't recognices my overloaded operator<< for the UnicodeString.
Here is a test program:
<snip>
I'm using gcc 4.4.5 on Ubuntu 11.04 and boost 1.42. Does someone know why the overloaded operator isn't used or how I can get the test program to work?
Keeping in mind that UnicodeString is defined in namespace icu_<some-version-number>, what you've pointed out is not limited to UnicodeString. The following simplified example apparently shows ADL failing for Boost.Variant when the streaming operator for Foo is defined in the global namespace instead of Foo's defining namespace. (gcc 4.0.1, boost 1.4.5)
#include <iostream> #include <boost/variant.hpp>
namespace Bar { struct Foo {}; }
std::ostream& operator<<(std::ostream& stream, Bar::Foo const &b) { return stream << "Foo"; }
int main() {
//Not compiles. boost::variant<Bar::Foo, char const *, int, double> test;
//Compiles. //Bar::Foo test;
test = Bar::Foo();
std::cout << test << std::endl;
return 0; }
Is this a bug in Boost.Variant?
IIUC operators can only be found reliably by ADL and must always be defined in an associated namespace. It will only work to put them in the global namespace if the calling code (in this case, variant serialization) were also in the global namespace, which wouldn't be good. Cheers, Gordon

On Sun, 09 Oct 2011 15:31:53 -0700, Gordon Woodhull <gordon@woodhull.com> wrote:
On Oct 9, 2011, at 3:12 PM, Mostafa <mostafa_working_away@yahoo.com> wrote:
<snip>
Keeping in mind that UnicodeString is defined in namespace icu_<some-version-number>, what you've pointed out is not limited to UnicodeString. The following simplified example apparently shows ADL failing for Boost.Variant when the streaming operator for Foo is defined in the global namespace instead of Foo's defining namespace. (gcc 4.0.1, boost 1.4.5)
#include <iostream> #include <boost/variant.hpp>
namespace Bar { struct Foo {}; }
std::ostream& operator<<(std::ostream& stream, Bar::Foo const &b) { return stream << "Foo"; }
int main() {
//Not compiles. boost::variant<Bar::Foo, char const *, int, double> test;
//Compiles. //Bar::Foo test;
test = Bar::Foo();
std::cout << test << std::endl;
return 0; }
Is this a bug in Boost.Variant?
IIUC operators can only be found reliably by ADL and must always be defined in an associated namespace. It will only work to put them in the global namespace if the calling code (in this case, variant serialization) were also in the global namespace, which wouldn't be good.
Hmmm ... It seems the issue isn't with the placement of the calling code in global namespace or not, but with the funny rule that unqualified name lookup does not go beyond some ancestor scope if any possible match is found in said ancestor. For example, even if the calling code in main() is moved into function some_func in namespaces Detail::Huh, the name lookup works (via unqualified name lookup in the global scope, before ADL kicks in) for Bar::Foo. And it fails for Boost.Variant because there is some possible match for operator<< associated with Boost.Variant which prevents a lookup in the global scope. (At least according to: http://stackoverflow.com/questions/4603886/c-operator-lookup-rules-koenig-lo...). Mostafa

On Oct 10, 2011, at 8:46 AM, Mostafa <mostafa_working_away@yahoo.com> wrote:
Hmmm ... It seems the issue isn't with the placement of the calling code in global namespace or not, but with the funny rule that unqualified name lookup does not go beyond some ancestor scope if any possible match is found in said ancestor.
I see, thanks. That is funny, but consistent. So it could find it in the global namespace, but not reliably, which is why you must rely on ADL instead.
participants (3)
-
André
-
Gordon Woodhull
-
Mostafa