J’observe un comportement plutôt étrange du code suivant:
#include #include #include #include #include #include "gsl.h" template using ImmutableValueRange = boost::any_range; template ImmutableValueRange make_transforming_immutable_range(const C& container) { return container | boost::adaptors::transformed([](const typename C::value_type& v) -> T { //std::cout << "trans : " << T{ v }.data() << "\n"; return T{ v }; }); } void f(ImmutableValueRange<gsl::cstring_span> r) { for (const auto& c : r) { std::cout << c.data() << "\n"; } } int main() { std::vector v({ "x", "y", "z" }); f(make_transforming_immutable_range<gsl::cstring_span>(v)); }
L’idée ici est d’isoler la représentation réelle d’une séquence de chaînes reçue en tant que paramètre par la fonction f
derrière un any_range
et gsl::ssortingng_span
(remarque, la validation qui modifie ssortingng_view
en ssortingng_span
a été effectuée il y a quelques heures). GSL).
Mon code d’origine ne any_range
pas de paramètre de modèle const T
as Reference
pour any_range
(il s’agissait d’un simple T
) et il s’est any_range
pendant l’exécution. Cependant, cela ne se produisait qu’en mode Release et fonctionnait parfaitement dans Debug ou RelWithDebInfo (généré par CMake). J’ai utilisé VS2013 / 2015 x64. De plus, essayer de déboguer la version complète de la version Release, en ajoutant une sortie de débogage à la conversion, lambda a éliminé le plantage (je suppose que cela a empêché l’inline). Ma dernière solution de travail consiste à spécifier const T
comme Reference
.
Cependant, je me demande toujours pourquoi l’accident s’est-il produit en premier lieu? Est-ce le bug du compilateur VS? Bug dans l’implémentation actuelle de ssortingng_span
? Ou suis-je simplement en boost::any_range
utiliser le boost::any_range
?
modifier
Vient de construire la version avec clang 3.7.0 et le comportement est similaire (fonctionne très bien en débogage et ne plante pas, mais génère des ordures sans const T
avec -O2
). Donc, cela ne semble pas être un problème de compilateur.
En fin de compte, la méthode de dereference
any_range
retournera une référence à T
sauf si le type Reference
est spécifié en tant que const T
, créant ainsi une référence suspendue à une variable temporaire. Cela est dû à l’utilisation de any_incrementable_iterator_interface::mutable_reference_type_generator
défini dans any_iterator_interface.hpp .
Par conséquent, la solution correcte au problème consiste en effet à spécifier const T
comme type de Reference
au cas où le déréférencement de l’iterator renvoie un temporaire.
Après un rapide coup d’œil, je soupçonne que le problème réside dans votre lambda. Si j’ai bien compris, vous finissez par prendre une référence std::ssortingng
by const avec la déclaration de paramètre suivante:
const typename C::value_type& v
Cependant, vous utilisez ensuite v
pour construire un cssortingng_span
. Voici le cssortingng_span
: cssortingng_span
seulement un constructeur qui va d’une référence non-constante à un type de conteneur (comme std::ssortingng
). Conceptuellement, le constructeur ressemble à ceci:
template
Je suppose donc que lorsque vous revenez de votre lambda, un temporaire est créé à partir de v
, puis transmis au constructeur cssortingng_span
afin de fournir un argument de référence non-const. Bien sûr, une fois que ce temporaire est nettoyé, votre cssortingng_span
est laissé en cssortingng_span
.