2017-07-17 13 views
-1

J'essaie de transformer un vecteur d'instances foo en une chaîne mais j'ai une erreur fatale sur std :: transform.erreur fatale sur std :: transformer C++

Say data a la valeur suivante:

[0] 
    [name] = John 
    [size] = 3423 

[1] 
    [name] = Joseph 
    [size] = 3413 

code:

struct foo { 
    foo(std::string n, size_t s) 
      : name(std::move(n)), 
       size(s) 
    { 
    } 
    std::string name; 
    size_t size; 
}; 

std::string server = "1"; 
std::vector<std::string> output; 
output.reserve(static_cast<unsigned_long>(std::distance(std::begin(data), std::end(data)))); 

std::transform(std::begin(data), 
       std::end(data), 
       std::begin(output), 
       [&, this](foo const& item){ 

      std::ostringstream result; 
      data << server << "," 
       << item.name << "," 
       << item.size << ";"; 
      return result.str(); 
     }); 

Lors du débogage, il arrête à la ligne *__result = __unary_op(*_first) de tranform mise en œuvre stl_algo.h passe ensuite à FatalConditionHandler du framework de test de capture. Je suis nouveau à la fois pour tester les tests et std :: transform. Quelqu'un peut-il expliquer ce qui pourrait causer le problème et comment le résoudre? Merci beaucoup!

+0

Est-ce que cela devrait être 'résultat << serveur << ...'? – BoBTFish

+1

'std :: vector :: reserve' ne fait pas ce que vous pensez. 'resize' est plus précis, mais même dans ce cas, vous pourriez vouloir éviter cela. – AndyG

Répondre

1

Vous avez réservé de l'espace dans output, mais vous avez laissé sa taille à zéro.

Vous allez ensuite écrire à travers son itérateur begin, comme s'il avait de l'espace pour contenir des données.

Ensuite, tout va "boom".

Au lieu d'écrire std:begin(output), pensez à utiliser std::back_inserter(output) comme l'itérateur de destination.

Vous avez aussi un autre problème: l'intérieur de votre lambda, vous avez:

 std::ostringstream result; 
     data << server << "," 
      << item.name << "," 
      << item.size << ";"; 
     return result.str(); 

Cela ressemble à une erreur assez évidente - vous avez sans doute l'intention:

 std::ostringstream result; 
     result << server << "," 
      << item.name << "," 
      << item.size << ";"; 
     return result.str(); 

Personnellement, je probablement structurer le code quelque peu différemment. Je aimerais ajouter quelque chose comme:

struct foo { 
    std::string name; 
    size_t size; 

    // new addition: 
    friend std::ostream &operator<<(std::ostream &os, foo const &f) { 
     return os << f.name << ',' << f.size; 
    } 
}; 

... alors le lambda dans votre transformation devient plutôt simple:

std::ostringstream result; 
result << server << "," item; 
return result.str(); 

Il pourrait toutefois être utile d'envisager de faire cela sans les stringstream itermediaries du tout . Dans ce cas, vous n'avez vraiment besoin que d'une concaténation de chaîne, et ils imposent beaucoup de frais généraux pour le faire.

struct foo { 
// ... 
    std::string to_string() { 
     return name + "," + size; 
    } 
}; 

Ensuite, le corps lambda devient:

return server + "," + item.to_string(); 

Shorter, plus simple, et presque certainement plus rapide.

+0

Merci beaucoup! C'est vraiment utile! – sabanana