Here's a testcase:
#include <istream>
#include <boost/lexical_cast.hpp>
namespace N {
enum class alarm_code_t {
BLAH
};
}
std::istream& operator>>(std::istream& is, N::alarm_code_t& code)
{
std::string tmp;
is >> tmp;
if (tmp == "BLAH")
code = N::alarm_code_t::BLAH;
else
is.setstate(std::ios::failbit);
return is;
}
int main()
{
auto code = boost::lexical_cast<N::alarm_code_t>("BLAH");
}
Boost rejects the conversion, claiming that there's no matching operator>>:
In file included from /usr/local/include/boost/iterator/iterator_categories.hpp:22:0,
from /usr/local/include/boost/iterator/iterator_facade.hpp:14,
from /usr/local/include/boost/range/iterator_range_core.hpp:27,
from /usr/local/include/boost/lexical_cast.hpp:30,
from main.cpp:2:
/usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp: In instantiation of 'struct boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<N::alarm_code_t> >':
/usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:270:89: required from 'struct boost::detail::deduce_target_char<N::alarm_code_t>'
/usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:404:92: required from 'struct boost::detail::lexical_cast_stream_traits<const char*, N::alarm_code_t>'
/usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:465:15: required from 'struct boost::detail::lexical_converter_impl<N::alarm_code_t, const char*>'
/usr/local/include/boost/lexical_cast/try_lexical_convert.hpp:174:44: required from 'bool boost::conversion::detail::try_lexical_convert(const Source&, Target&) [with Target = N::alarm_code_t; Source = char [5]]'
/usr/local/include/boost/lexical_cast.hpp:42:60: required from 'Target boost::lexical_cast(const Source&) [with Target = N::alarm_code_t; Source = char [5]]'
main.cpp:25:60: required from here
/usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:243:13: error: static assertion failed: Target type is neither std::istream`able nor std::wistream`able
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
(demo)
However, the code works as advertised when I declare/define operator>> inside namespace N.
Why's that? Why does the lookup otherwise fail?
Since the call to
operator>>is made fromboost::lexical_cast<>function template, the second argument tooperator>>is a dependent name:In other words, non-ADL lookup is not performed from the template instantiation context.
The global namespace is not considered because none of the arguments of the call have any association with the global namespace.
operator>>(std::istream& is, N::alarm_code_t& code)is not declared in namespaceN, hence ADL does not find it.These name-lookup oddities are documented in N1691 Explicit Namespaces.