Existe-t-il un moyen d'utiliser ces opérateurs pour entrer et sortir des données binaires? La raison pour laquelle je veux faire ceci est que cela rend le code lisible. Ex: infile >> filedecrypter >> metadataparser >> audiodecoder >> effets >> soundplayer;Comment utiliser les opérateurs >> et << pour les données binaires en C++?
Répondre
En effet, cela peut être fait, si la bibliothèque ou votre code fournit les surcharges pour operator<<
et operator>>
pour que cela fonctionne. Exemple simple sur la façon dont on pourrait le faire:
class transformer {
public:
virtual std::iostream& transform(std::iostream&) = 0;
};
class noise : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
class echo : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
std::iostream& operator>>(std::iostream& io, transformer& ts) {
return ts.transform(io);
}
int main() {
std::stringstream data;
std::ifstream file("sound.wav");
noise n; echo e;
data << file.rdbuf();
data >> n >> e;
/* pipelined data now ready to be played back */
}
Le problème avec l'aide d'un std::istream
pur est que vous lire, mais vous n'auriez pas un moyen de mettre les données en arrière transformées pour l'étape suivante de la pipeline. Donc j'utilise std::iostream
ici. Cette approche ne semble pas efficace, car chaque opérateur >> appel extrairait l'ensemble des données, et les réintégrerait.
Pour avoir un moyen plus performant de diffuser ce serait de créer un expression template
. Cela signifie, alors que operator>>
est appelé, vous ne faites pas transformantes encore, mais vous revenez types d'expression qui enregistrera la chaîne des opérations dans son type:
typedef transform< echo< noise<istream> > > pipeline;
std::ifstream file("file.wav");
pipeline pipe(file);
int byte = pipe.get();
serait un exemple de ce type. La structure des pipelines est décodée dans le type lui-même. Par conséquent, aucune fonction virtuelle n'est plus nécessaire dans le pipeline. Ce n'est pas construit à la demande, mais en utilisant typedef ici, pour montrer le principe. La programmation d'un tel système n'est pas facile. Donc, vous devriez probablement regarder dans les systèmes existants, comme Boost.Iostreams (voir ci-dessous). Pour vous donner une idée comment il ressemblerait, voici un exemple que je viens codé pour vous :):
#include <iostream>
template<typename T>
struct transformer {
int get() {
return static_cast<T*>(this)->read();
}
};
struct echot {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() + 1;
}
chain(Chain const& c):c(c) { }
};
} echo;
struct noiset {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() * 2;
}
chain(Chain c):c(c) { }
};
} noise;
template<typename T>
typename T::template chain<std::istream&> operator>>(std::istream& is, T) {
return typename T::template chain<std::istream&>(is);
}
template<typename T, typename U>
typename U::template chain<T> operator>>(T t, U u) {
return typename U::template chain<T>(t);
}
int main() {
std::cout << (std::cin >> echo >> noise).get() << std::endl;
}
Entrée 0 donne le code ASCII 48 ici, qui est ajouté 1, et multiplié par 2, donnant une valeur de 98, qui est également finalement sortie. Je pense que vous êtes d'accord que ce n'est pas un code qu'un débutant voudrait écrire. Alors peut-être regarder dans boost. Boost a une bibliothèque iostreams sophistiquée, qui peut faire beaucoup de choses. Je suis sûr que vous trouverez quelque chose de convenable à cela. Boost.Iostreams
Bien sûr que cela peut être fait. Il suffit de définir votre propre opérateur >> et l'opérateur < < ils font « la bonne chose » ...
Je le ferais donc j'avoir des méthodes dans la classe, comme toStream (ostream & os) et fromStream (istream &), puis définissez
istream& operator>> (istream& is, T& t)
{
t.fromStream(is);
return t;
}
ostream& operator<< (ostream& os, const T& t)
{
t.toStream(os);
return t;
}
Il n'y a pas besoin d'utiliser les flux pour déplacer les données. Vous pouvez créer vos propres classes pour le faire. Cela montre un exemple. Évidemment, les classes Decrypt et MetaDataParser peuvent être des classes de base abstraites avec des fonctions virtuelles permettant de brancher plusieurs fonctionnalités.
#include <iostream>
#include <istream>
using namespace std;
class Data2
{
};
class Data3
{
};
class Decrypt
{
};
class MetaDataParser
{
};
Data2& operator>>(istream& in, Decrypt& decrypt)
{
return *new Data2;
}
Data3& operator>>(Data2& d2, MetaDataParser& mdp)
{
return *new Data3;
}
int main()
{
Decrypt decrypt;
MetaDataParser mdp;
cin >> decrypt >> mdp;
}
Juste pour être clair, avez-vous l'intention de dupliquer la sémantique de iostreams? Parce que vous semblez proposer quelque chose de différent. Dans l'exemple que vous donnez:
infile >> filedecrypter >> metadataparser >> audiodecoder >> effects >> soundplayer;
En iostreams, le sens ici est de lire infile en filedecrypter jusqu'à ce que vous arrivez à des espaces, puis de infile en metadataparser jusqu'à plus des espaces, et ainsi de suite.
On dirait que vous proposez quelque chose de différent, où metadataparser lit de filedecrypter, audiodecoder de metadataparser, etc. Dans ce cas, je pense que la réponse à votre question doit être qualifié un peu.
Pouvez-vous utiliser l'opérateur >> pour exprimer cette construction? Probablement oui.
Pouvez-vous utiliser iostreams pour cela? Probablement pas.
Je vous suggère de préciser ce que cela signifie quand vous dites A >> B. exprimer Peut-être que les méthodes régulières plutôt que l'opérateur premier surcharge, et qui peut clarifier la question.
OK. Je voulais dire quelque chose comme: Play (ApplyEffects (Decode (ExtractMetaData (Decrypt (BinaryFileRead (
- 1. C++ fstream << and >> opérateurs avec des données binaires
- 2. SortedList <>, SortedDictionary <> et Dictionary <>
- 3. Listes chaînées, polynômes, opérateurs surchargés << and >> en C++
- 4. Quand faut-il utiliser <%# ... %> et <%= ... %>?
- 5. priority_queue <> comparaison pour les pointeurs?
- 6. Remplacer tous les <br> avec <br />
- 7. <type1> '<typename>' doit mettre en œuvre '<membername>' pour l'interface '<interfacename>'
- 8. Comment créer un effet désactivé sur les tags <input>, <select> et <img> avec jQuery?
- 9. XPaths et <? ?>
- 10. <?> vs <T>
- 11. Refactoring Func <T> en Expression <Func<T>>
- 12. <MailDefinition> et <%%> espaces réservés
- 13. Comment puis-je réduire IEnumerable <IEnumerable <Foo>> à IEnumerable <Foo>?
- 14. Dans MVC, quand utilisez-vous <%= %> et <% %>?
- 15. C# - delegate System.Func < >
- 16. EntitySet <IEnumerable <T>> pour IEnumerable <T>
- 17. Comment jeter Expression <Func <T, DateTime>> à l'expression <Func <T, object>>
- 18. Gridview et List <>
- 19. <autorisation> peut protéger les pages?
- 20. Comment utiliser <xmlpeek> dans NAnt
- 21. comment exploser <br><br/><br /> tags dans une chaîne?
- 22. Obtenez un IEnumerable <T> d'un IEnumerable <IEnumerable <T>>
- 23. << and >> symboles dans Erlang
- 24. <iostream> vs vs <iostream.h> « iostream.h »
- 25. Analyse simple du fichier html pour les valeurs <U></U> dans .net?
- 26. Comment le changement Liste <T> données IQueryable <T> données
- 27. Comment fonctionne <iostream>? (C++)
- 28. Comment faire pour ajuster >> et << comportement dans Emacs (Vim émulation, indent, dedent)?
- 29. Manipulation <td> dans différents <tr>
- 30. quand utiliser Collection <T> vs Liste <T>
Le souci d'efficacité pourrait probablement être atténué par le passage d'une procuration d'une sorte plutôt que d'un flux de données lourdes. –
il faut lire en utilisant paresseusement une expression template.that serait la façon de le faire i think.the modèle d'expression enregistrerait la structure de pipeline, et pourrait enchaîner les données à travers différents steps.but je pense qu'il vaut mieux pour lui montrer ce flux de base , au lieu de lui faire peur avec des modèles. –
Les modèles sont bien :) En fait, j'ai déjà mis en œuvre quelque chose de très similaire. Ce qui m'a attiré à ces opérateurs était que vous pouviez utiliser le pipeline comme un modèle push ou pull (inversé pour la sortie). – Carl