为什么lexical_cast要求operator >>在匹配的命名空间中?

Lig*_*ica 10 c++ boost lexical-cast c++11

这是一个测试用例:

#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");
}
Run Code Online (Sandbox Code Playgroud)

Boost拒绝转换,声称没有匹配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),
Run Code Online (Sandbox Code Playgroud)

(演示)

但是,当我声明/定义operator>>内部命名空间时,代码的工作方式与广告一样N.

为什么?为什么查找会失败?

Max*_*kin 14

由于调用operator>>是从boost::lexical_cast<>函数模板进行的,因此第二个参数operator>>依赖名称:

查找规则

正如在lookup中所讨论的那样,模板中使用的从属名称的查找被推迟,直到模板参数已知,此时

  • 非ADL查找使用从模板定义上下文可见的外部链接检查函数声明

  • ADL使用从模板定义上下文模板实例化上下文都可见的外部链接检查函数声明

(换句话说,在模板定义之后添加新的函数声明不会使其显示,除非通过ADL)...这样做的目的是帮助防止违反ODR进行模板实例化.

换句话说,不从模板实例化上下文执行非ADL查找.

不考虑全局命名空间,因为调用的任何参数都与全局命名空间没有任何关联.

operator>>(std::istream& is, N::alarm_code_t& code)未在命名空间中声明N,因此ADL找不到它.


N1691显式命名空间中记录了这些名称查找奇怪的内容.