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");
}

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),

(デモ)

operator>>ただし、 namespace 内で宣言/定義すると、コードは宣伝どおりに機能しますN

なぜですか?それ以外の場合、ルックアップが失敗するのはなぜですか?

4

3 に答える 3

15

への呼び出しは関数テンプレートoperator>>から行われるため、への 2 番目の引数は従属名です。boost::lexical_cast<>operator>>

ルックアップ ルール

ルックアップで説明したように、テンプレートで使用される従属名のルックアップは、テンプレートの引数が判明するまで延期されます。

  • 非 ADL ルックアップは、テンプレート定義コンテキストから見える外部リンケージを持つ関数宣言を調べます

  • ADL は、テンプレート定義コンテキストテンプレート インスタンス化コンテキストの両方から見える外部リンケージを持つ関数宣言を調べます

(つまり、テンプレート定義の後に新しい関数宣言を追加しても、ADL を介した場合を除いて、それは表示されません)... この規則の目的は、テンプレートのインスタンス化の ODR 違反を防ぐことです。

つまり、非 ADL ルックアップはテンプレート インスタンス化コンテキストから実行されません。

呼び出しのどの引数もグローバル名前空間と関連付けられていないため、グローバル名前空間は考慮されません。

operator>>(std::istream& is, N::alarm_code_t& code)は namespaceNで宣言されていないため、 ADLはそれを検出しません。


これらの名前検索の奇妙な点は、N1691 Explicit Namespacesに記載されています。

于 2016-08-15T15:15:15.323 に答える