Boujour � tous
Je me retrouve avec un probl�me quelque peu tordu.
Dans mon �quipe, nous avons un g�n�rateur de code, qui prend une description de format de fichiers CSV en entr�e.
L'id�e, c'est d'abbr�ger fortement le temps d'�criture des validations des donn�es, tout en offrant assez de souplesse � l'usage.
L'une de mes contraintes, c'est que ni C++11 ni Boost ne sont autoris�s (j'ai d� r�cup�rer optional lite pour avoir un optional correct)
Le code g�n�r� devrait ressembler � ceci:
Au passage, j'aimerai bien trouver un moyen d'�crire de partager la d�finition de type entre Bidule et Bidule_format...
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 class Bidule { public: typedef types::string::value_type champ1_type; typedef types::optional_integer::value_type champ2_type; private: champ1_type champ1; champ2_type champ2; public: Bidule(champ1_type const& champ1, champ2_type const& champ2) : champ1(champ1), champ2(champ2) {} champ1_type const& getChamp1() const {return champ1;} champ1_type & getChamp1() {return champ1;} champ2_type const& getChamp2() const {return champ2;} champ2_type & getChamp2() {return champ2;} }; class Bidule_format { private: types::string champ1; types::decimal champ2; public: //les constructeurs des types permettent les réglages de validations en lecture et écriture Bidule_format() : champ1(8), champ2(4) {} //produce a value from internal state Bidule operator()() const { return Bidule( champ1(), champ2() ); } Bidule_format& clear() { champ1.clear(); champ2.clear(); return *this; } //set internal state according to value, and return itself Bidule_format & operator()(Bidule const& source) { champ1(source.getChamp1()); champ2(source.getChamp2()); return *this; } Bidule_format & from(std::istream& stream) { stream >> champ1 >> champ2; return *this; } Bidule_format const& into(std::ostream& stream) const { stream << champ1 << champ2; return *this; } };
sauf que la pr�d�claration de Bidule n'est pas suffisante pour Bidule_format::operator()(), et que Bidule utiliserait Bidule_format::champ1_type::value_type
Il s'agit donc d'�crire dans une biblioth�que tout le code qui ne changerait pas d'une description � l'autre.
Et c'est l� que mes soucis commencent.
J'ai une classe extractor qui me sert de base pour les diff�rents types.
types::integer, types::optional_string, etc sont h�riti�res de extractor.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 class extractor_base { public: virtual ~extractor() {} virtual void from(std::istream & stream) = 0; virtual void into(std::ostream & stream) const = 0; virtual void clear() =0; }; inline std::istream& operator>> (std::istream& stream, extractor_base & extractor) { extractor.from(stream); return stream; } inline std::ostream& operator<<(std::ostream& stream, extractor_base const & extractor) { extractor.into(stream); return stream; } template <typename T, bool optional = false> class extractor : public extractor_base{ public: typedef T concrete_type; typedef typename option_type<T, optional>::value_type value_type;//std::optional<T> ou T, selon que optional soit vrai ou non private: value_type v; protected: explicit extractor() {} explicit extractor(value_type const& v) : v(v) {} public: virtual ~extractor() {} value_type const& operator() () const {return v;} value_type & operator() () {return v;} void operator() (value_type const& value) {v = value;} virtual void clear() {v=value_type();} };
Sauf que j'ai deux mutualisations possibles, que je n'arrive pas � �crire correctement:
D'un cot�, integer et optional_integer ont le m�me format.
De l'autre, les optional ont la m�me interaction avec les flux, et les autres types en partage une autre
Typiquement, je peux �crire
Sauf que la dedans, format() et extract() sont li�es au types (les memes fonctions pour integer et optional_integer)
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 template <typename Value> class strict_type : public extractor<Value, false> { public: virtual void from(std::istream & stream) { set(extract(next(stream))); } virtual void into(std::ostream & stream) const { stream << format(get()) << delimiter(); } }; template <typename Value> class optional_type : public extractor<Value, true> { public: virtual void from(std::istream & stream) { std::string token = next(stream); if (empty(token)) { set(optional::none); } else { set(extract(token)); } } virtual void into(std::ostream & stream) const { if (get()) { stream << format(*get()); } stream << delimiter(); } };
Et c'est la que je suis un peu perdu.
Comment continueriez-vous cette architecture?
J'ai au moins une contrainte sur le choix: scientific et decimal sont deux types ayant des formats diff�rents, mais utilisant double comme type concret.
C'est ce qui m'a pouss� jusque l� � ne pas partir sur des sp�cialisations.
Je peux faire pas mal de chaos la dedans, les fonctions de formatage sont des fonctions libres (r�cup�r�es pour le moment).
Partager