11
votes

Pourquoi lexical_cast exige-t-il que l'opérateur >> soit dans un espace de noms correspondant?

Voici une test:

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


4 commentaires

Problème de l'ADL standard de la tourbière?


@ T.c.: Hmm ... Autre Opérateur >> trouvé dans le pages de noms N Par conséquent espace de noms global et ce particulier opérateur >> non trouvé? Mais je n'ai pas un autre opérateur >> dans n . Ou tout, en fait. Je ne peux pas grok où l'adl vient à elle.


ADL s'engage à ce que votre opérateur >> s second type de paramètre est n :: alarm_code_t , donc n est un espace de noms associé et sera recherché la définition de l'opérateur.


@Praetorian the >> appelle dans Espace de noms boost . Je pense que la question de Lrio est "pourquoi n'est-ce pas l'opérateur >> dans espace de noms :: aussi considéré quand >> est invoqué dans Espace de noms Boost ? " Dire "il n'est pas trouvé par ADL" seulement répond à la moitié de la question: ADL n'est pas la seule recherche.


3 Réponses :


15
votes

Depuis l'appel à Opérateur >> est fabriqué à partir de Boost :: Lexical_cast <> Modèle de fonction, le deuxième argument à Opérateur >> est un Nom en fonction :

règles de recherche

Comme indiqué dans la recherche, la recherche d'un nom dépendant utilisé dans un modèle est reportée jusqu'à ce que les arguments de modèle soient connus, à quelle heure

  • recherche non ADL examine les déclarations de fonction avec une liaison externe visible à partir du contexte de définition modèle

  • ADL examine les déclarations de fonction avec une liaison externe visible à partir du contexte de définition modèle et du contexte d'instanciation de modèle

    (En d'autres termes, l'ajout d'une nouvelle déclaration de fonction après la définition de modèle ne le rend pas visible, sauf via ADL) ... Le but de ceci est que la règle est de vous aider à protéger contre les violations de l'ODR pour les instanciations de modèles.

    En d'autres termes, la recherche non-ADL n'est pas effectuée à partir du contexte d'instanciation modèle .

    L'espace de noms global n'est pas pris en compte car aucun des arguments de l'appel n'a d'association avec l'espace de noms global.

    opérateur >> (std :: istream & is, n :: alarm_code_t & code) n'est pas déclaré dans Namespace n , donc ADL ne le trouve pas.

    Ces bizarreries de recherche sont documentées dans N1691 espaces de noms explicites .


0 commentaires

4
votes

J'ai réécrit l'exemple un peu: xxx

maintenant faux_opérateur pour N :: AC n'est pas défini dans FakeBoost , il n'est pas non plus défini dans n (donc pas ADL), donc faux_cast ne le trouvera pas.

Le message d'erreur est un bit de consus (car boost). Pour mon exemple, c'est: xxx

qui explique beaucoup.



2
votes

Une fois opérateur >> code> se trouve dans boost namespace code>, il cesse de regarder dans les espaces de noms clos. Il, cependant, faire aussi une recherche d'ADL.

  template<class T>
  void do_foo( T t ) {
    foo(t);
  }
}

namespace B{
  struct bar {};
}

void foo(B::bar) {
  std::cout << "foobar!\n";
}


2 commentaires

Même si Nomspace Boost boost contient zéro opérateur >> s, :: opérateur >> ne sera toujours pas trouvé par une recherche ordinaire non qualifiée parce que cela seulement considère le contexte de définition du modèle.


@ T.c. Si vous avez défini >> avant d'inclure l'en-tête, il serait trouvé. ;)