IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Conception d'un pipeline générique


Sujet :

Langage C++

  1. #21
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Une autre possibilité, basée à la fois sur celle présentée ci-dessus et sur une récursivité des basic_pipeline<>.

    pipeline<F1,F2,F3,F4> == basic_pipeline<F1,basic_pipeline<F2,basic_pipeline<F3,F4> > >;

    (en fait, l'égalité n'est pas totalement vraie : il s'agit d'une instance interne).

    Je n'ai pas rajouté les fonctions make_pipeline (elles sont triviales à écrire).

    Le code est quand même plus compact à écrire, mais il reste relativement agaçant, du haut de ses 700+ lignes.

    Je vais tenter d'implémenter des fonctions stage<X>(pipeline), histoire d'être capable de modifier un étage particulier du pipeline.

    (je n'ai pas testé le code, mais il me semble correct ; quoi qu'il en soit, c'est juste un code d'exemple, une proposition).

    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
     
    #ifndef ekogen_pipeline_h
    #define ekogen_pipeline_h
     
    namespace ekogen {
     
    	// end recursion, if needed
    	struct nulltype { };
     
    	// this class need to be specialized before use
    	template <class F>
    	struct stage_traits
    	{ };
     
    	// basic_pipeline<F1,F2>: a partial pipeline, built of two functions
    	// the second one might be a partial pipeline as well.
    	template <class F1, class F2>
    	class basic_pipeline
    	{
    	public:
    		typedef typename stage_traits<F1>::input_type input_type;
    		typedef typename stage_traits<F2>::output_type output_type;
    		typedef F1 function1_type;
    		typedef F2 function2_type;
     
    	private:
    		function1_type m_function1;
    		function2_type m_function2;
     
    	private:
    		typedef typename stage_traits<F1>::output_type input2_type;
     
    	public:
    		basic_pipeline()
    		{ }
     
    		basic_pipeline(const function1_type& f1, const function2_type& f2)
    		: m_function1(f1), m_function2(f2)
    		{ }
     
    		basic_pipeline(const basic_pipeline& other)
    		: m_function1(other.m_function1)
    		, m_function2(other.m_function2)
    		{ }
     
    		~basic_pipeline()
    		{ }
     
    		basic_pipeline& operator=(const basic_pipeline& other)
    		{
    			basic_pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(basic_pipeline& other)
    		{
    			std::swap(m_function1, other.m_function1);
    			std::swap(m_function2, other.m_function2);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			input2_type input2;
    			stage_traits<function1_type>::execute(m_function1, input, input2);
    			stage_traits<function2_type>::execute(m_function2, input2, output);
    		}
    	};
     
    	// basic_pipeline<F1>: a partial pipeline, built of only one function
    	template <class F1>
    	class basic_pipeline<F1, nulltype>
    	{
    	public:
    		typedef typename stage_traits<F1>::input_type input_type;
    		typedef typename stage_traits<F1>::output_type output_type;
    		typedef F1 function_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		basic_pipeline()
    		{ }
     
    		basic_pipeline(const function_type& function)
    		: m_function(function)
    		{ }
     
    		basic_pipeline(const basic_pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~basic_pipeline()
    		{ }
     
    		basic_pipeline& operator=(const basic_pipeline& other)
    		{
    			basic_pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(basic_pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			stage_traits<function_type>::execute(input, output);
    		}
     
    	};
     
    	// any pipeline is now of type basic_pipeline<F1,basic_pipeline<F2,basic_pipeline<...,nulltype> > >
    	// we just need to encapsulate this...
     
    	// these are going to be specialized below
    	template <class,class,
    			class,class,
    			class,class,
    			class,class,
    			class,class>
    	class pipeline;
     
    	// pipeline<F1>
    	template <class F1>
    	class pipeline<F1,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F1,nulltype> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1)
    		: m_function(f1)
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,F2>
    	template <class F1,class F2>
    	class pipeline<F1,F2,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F1,F2> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2)
    		: m_function(f1,f2)
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,F2,F3>
    	template <class F1,class F2,class F3>
    	class pipeline<F1,F2,F3,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F2,F3> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3)
    		: m_function(f1, level1_stage(f2,f3))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F4>
    	template <class F1,class F2,class F3,class F4>
    	class pipeline<F1,F2,F3,F4,nulltype,nulltype,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F3,F4> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4)
    		: m_function(f1, level1_stage(f2, level2_stage(f3,f4)))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F5>
    	template <class F1,class F2,class F3,class F4,class F5>
    	class pipeline<F1,F2,F3,F4,F5,nulltype,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F4,F5> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5)
    		: m_function(f1, level1_stage(f2, level2_stage(f3,level3_stage(f4,f5))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F6>
    	template <class F1,class F2,class F3,class F4,class F5,class F6>
    	class pipeline<F1,F2,F3,F4,F5,F6,nulltype,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F5,F6> level4_stage;
    		typedef basic_pipeline<F4,level4_stage> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, const F6& f6)
    		: m_function(f1,level1_stage(f2, level2_stage(f3,level3_stage(f4,level4_stage(f5,f6)))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F7>
    	template <class F1,class F2,class F3,class F4,class F5,class F6,class F7>
    	class pipeline<F1,F2,F3,F4,F5,F6,F7,nulltype,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F6,F7> level5_stage;
    		typedef basic_pipeline<F5,level5_stage> level4_stage;
    		typedef basic_pipeline<F4,level4_stage> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, const F6& f6, const F7& f7)
    		: m_function(f1,level1_stage(f2, level2_stage(f3,level3_stage(f4,level4_stage(f5,level5_stage(f6,f7))))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F8>
    	template <class F1,class F2,class F3,class F4,class F5,class F6,class F7,class F8>
    	class pipeline<F1,F2,F3,F4,F5,F6,F7,F8,nulltype,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F7,F8> level6_stage;
    		typedef basic_pipeline<F6,level6_stage> level5_stage;
    		typedef basic_pipeline<F5,level5_stage> level4_stage;
    		typedef basic_pipeline<F4,level4_stage> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, const F6& f6, const F7& f7, const F8& f8)
    		: m_function(f1,level1_stage(f2, level2_stage(f3,level3_stage(f4,level4_stage(f5,level5_stage(f6,level6_stage(f7,f8)))))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F9>
    	template <class F1,class F2,class F3,class F4,class F5,class F6,class F7,class F8,class F9>
    	class pipeline<F1,F2,F3,F4,F5,F6,F7,F8,F9,nulltype>
    	{
    	public:
    		typedef basic_pipeline<F8,F9> level7_stage;
    		typedef basic_pipeline<F7,level7_stage> level6_stage;
    		typedef basic_pipeline<F6,level6_stage> level5_stage;
    		typedef basic_pipeline<F5,level5_stage> level4_stage;
    		typedef basic_pipeline<F4,level4_stage> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9)
    		: m_function(f1,level1_stage(f2, level2_stage(f3,level3_stage(f4,level4_stage(f5,level5_stage(f6,level6_stage(f7,level7_stage(f8,f9))))))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// pipeline<F1,...,F10>
    	template <class F1,class F2,class F3,class F4,class F5,class F6,class F7,class F8,class F9,class F10>
    	class pipeline<F1,F2,F3,F4,F5,F6,F7,F8,F9,F10>
    	{
    	public:
    		typedef basic_pipeline<F9,F10> level8_stage;
    		typedef basic_pipeline<F8,level8_stage> level7_stage;
    		typedef basic_pipeline<F7,level7_stage> level6_stage;
    		typedef basic_pipeline<F6,level6_stage> level5_stage;
    		typedef basic_pipeline<F5,level5_stage> level4_stage;
    		typedef basic_pipeline<F4,level4_stage> level3_stage;
    		typedef basic_pipeline<F3,level3_stage> level2_stage;
    		typedef basic_pipeline<F2,level2_stage> level1_stage;
    		typedef basic_pipeline<F1,level1_stage> function_type;
    		typedef typename stage_traits<function_type>::input_type input_type;
    		typedef typename stage_traits<function_type>::output_type output_type;
     
    	private:
    		function_type m_function;
     
    	public:
    		pipeline(const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9, const F10& f10)
    		: m_function(f1,level1_stage(f2, level2_stage(f3,level3_stage(f4,level4_stage(f5,level5_stage(f6,level6_stage(f7,level7_stage(f8,level8_stage(f9,f10)))))))))
    		{ }
     
    		pipeline()
    		: m_function()
    		{ }
     
    		pipeline(const pipeline& other)
    		: m_function(other.m_function)
    		{ }
     
    		~pipeline()
    		{ }
     
    		pipeline& operator=(const pipeline& other)
    		{
    			pipeline(other).swap(*this);
    			return *this;
    		}
     
    		void swap(pipeline& other)
    		{
    			std::swap(m_function, other.m_function);
    		}
     
    		void execute(const input_type& input, output_type& output)
    		{
    			m_function.execute(input, output);
    		}
     
    		output_type operator()(const input_type& input)
    		{
    			output_type output;
    			m_function.execute(input, output);
    			return output;
    		}
    	};
     
    	// Some classical specializations for stage_traits<>.
    	// If you need some more, you'll have to build them.
     
    	template <class R,class A>
    	struct stage_traits<R(A)> // shall validate both function objects and function pointers
    	{
    		typedef A input_type;
    		typedef R output_type;
     
    		template <class F>
    		static void execute(F function, const input_type& input, output_type& out)
    		{
    			out = function(input);
    		}
    	};
     
    	// stage is a full fledge pipeline
    	template <class F1,class F2,class F3,class F4,class F5,class F6,class F7,class F8,class F9,class F10>
    	struct stage_traits<pipeline<F1,F2,F3,F4,F5,F6,F7,F8,F9,F10> >
    	{
    		typedef pipeline<F1,F2,F3,F4,F5,F6,F7,F8,F9,F10> function_type;
    		typedef typename function_type::input_type input_type;
    		typedef typename function_type::output_type output_type;
     
    		static void execute(const function_type& function, const input_type& input, output_type& out)
    		{
    			function.execute(input, output);
    		}
    	};
     
    	// stage is a basic_pipeline (essentially, a partial pipeline)
    	template <class F1,class F2>
    	struct stage_traits<basic_pipeline<F1,F2> >
    	{
    		typedef basic_pipeline<F1,F2> function_type;
    		typedef typename function_type::input_type input_type;
    		typedef typename function_type::output_type output_type;
     
    		static void execute(const function_type& function, const input_type& input, output_type& out)
    		{
    			function.execute(input, output);
    		}
    	};
     
     
    }
     
    #endif // ekogen_pipeline_h
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  2. #22
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Pas bien pour exactement la même raison ; du coup, pour faire un vrai pipeline, il est obligé de spécifier le type d'entrée et de sortie de chaque étage lorsqu'il instancie le pipeline ; et ça, c'est déjà moins beau (10 paramètres templates pour deux étages de pipeline (construction de l'instance de pipe_stream2).
    Disons que pour de la vision, on a en général besoin de chainage avec des entrées sorties / supplémentaires par rapport à un "pur" pipeline.
    Je vais suivre ce thread avec intérêt en tout cas. Je manque cruellement de temps pour faire plus que juste suivre par contre...

  3. #23
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Voila une version proto assez basique. Elle attends des instance d'objets fonctions polymorphes via task. La composition ets triviale, reste a remplacer task(truc()) en quelquechose de plus sexy mais c'est assez simple je pense.

    Le code effectif fait genre 100 lignes avec commentaires.

    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
    #include <iostream>
    #include <boost/proto/proto.hpp>
     
    namespace bp = boost::proto;
     
    // -----------------------------------------------------------------------------
    // function_ is a small holder for user-defined PFO instance
    // -----------------------------------------------------------------------------
    template<class Func> 
    struct function_
    {
      typedef Func callable_type;
     
      function_(Func const& f) : callable(f) {}
      Func callable;
    };
     
    // -----------------------------------------------------------------------------
    // perform is a callable transform that take a function_ terminal and execute it
    // -----------------------------------------------------------------------------
    struct perform : bp::callable
    {
      template<class Sig> struct result;
      template<class This, class Func, class In>
      struct result<This(Func,In)> 
           : boost::result_of<typename bp::detail::uncvref<Func>::type::callable_type(In)> {};
     
      template<class Func, class In>
      typename result<perform(Func,In)>::type
      operator()( Func& f, In& in ) const
      {
        return f.callable(in);
      }
    };
     
     
    // -----------------------------------------------------------------------------
    // Grammar for chaining pipe of functions
    // -----------------------------------------------------------------------------
    struct pipeline_grammar
    : bp::or_< bp::when< bp::terminal< function_<bp::_> >
                       , perform(bp::_value,bp::_state) 
                       >
             , bp::when< bp::bitwise_or<pipeline_grammar,pipeline_grammar>
                       , pipeline_grammar( bp::_right
                                         , pipeline_grammar(bp::_left,bp::_state)
                                         )
                       >
             >
    {};
     
     
    // -----------------------------------------------------------------------------
    // Forward declaration of the pipeline domain
    // -----------------------------------------------------------------------------
    struct pipeline_domain;
     
    // -----------------------------------------------------------------------------
    // A pipeline is the top level DS entity
    // -----------------------------------------------------------------------------
    template<class Expr>
    struct  pipeline
    : bp::extends<Expr,pipeline<Expr>, pipeline_domain>
    {
      typedef bp::extends<Expr, pipeline<Expr>, pipeline_domain> base_type;
      pipeline(Expr const &expr = Expr()) : base_type(expr) {}
     
      // ---------------------------------------------------------------------------
      // A pipeline is an unary callable object
      // ---------------------------------------------------------------------------
      template<class Input>
      typename boost::result_of<pipeline_grammar(pipeline,Input)>::type
      operator()(Input const& in) const
      {
        pipeline_grammar evaluator;
        return evaluator(*this,in);
      }
    };
     
     
    // -----------------------------------------------------------------------------
    // the pipeline_domain make pipeline expression macthes pipeline_grammar
    // -----------------------------------------------------------------------------
    struct pipeline_domain 
         : bp::domain<bp::generator<pipeline>,pipeline_grammar>
    {};
     
     
    // -----------------------------------------------------------------------------
    // Takes a PFO instance and make it a pipeline terminal
    // -----------------------------------------------------------------------------
    template<class Func>
    typename bp::result_of::
    make_expr<bp::tag::terminal, pipeline_domain,function_<Func> >::type
    task( Func const& f )
    {
      return bp::make_expr<bp::tag::terminal,pipeline_domain>( function_<Func>(f) );
    }
     
    //--------------------------- Examples --------------------
     
    struct return_value
    {  
      template<class Sig> struct result;
      template<class This, class T>
      struct result<This(T)> : bp::detail::uncvref<T>
      {};
     
      return_value(int i = 1) : factor(i) {}
     
      template<class T> 
      T operator()(T const& in) const
      {
        return in*factor;
      }
     
      int factor;
    };
     
    struct say_hi
    {
      typedef void result_type;
     
      template<class T> 
      void operator()(T const& in) const
      {
        std::cout << "Hi from value = " << in << "\n";
      }
    };
     
    int main()
    {
      return_value r1,r2(5);
      (task(r1) | task(r2) | task(say_hi())) (7); // SHould print 35
     
     
      float k = 10,r;
      r = (task(r2) | task(r2) | task(r2) | task(r2))(k);
      std::cout << r << "\n"; // Should print 6250
    }

  4. #24
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Voila une version proto assez basique. Elle attends des instance d'objets fonctions polymorphes via task. La composition ets triviale, reste a remplacer task(truc()) en quelquechose de plus sexy mais c'est assez simple je pense.

    Le code effectif fait genre 100 lignes avec commentaires.

    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
    #include <iostream>
    #include <boost/proto/proto.hpp>
     
    namespace bp = boost::proto;
     
    // -----------------------------------------------------------------------------
    // function_ is a small holder for user-defined PFO instance
    // -----------------------------------------------------------------------------
    template<class Func> 
    struct function_
    {
      typedef Func callable_type;
     
      function_(Func const& f) : callable(f) {}
      Func callable;
    };
     
    // -----------------------------------------------------------------------------
    // perform is a callable transform that take a function_ terminal and execute it
    // -----------------------------------------------------------------------------
    struct perform : bp::callable
    {
      template<class Sig> struct result;
      template<class This, class Func, class In>
      struct result<This(Func,In)> 
           : boost::result_of<typename bp::detail::uncvref<Func>::type::callable_type(In)> {};
     
      template<class Func, class In>
      typename result<perform(Func,In)>::type
      operator()( Func& f, In& in ) const
      {
        return f.callable(in);
      }
    };
     
     
    // -----------------------------------------------------------------------------
    // Grammar for chaining pipe of functions
    // -----------------------------------------------------------------------------
    struct pipeline_grammar
    : bp::or_< bp::when< bp::terminal< function_<bp::_> >
                       , perform(bp::_value,bp::_state) 
                       >
             , bp::when< bp::bitwise_or<pipeline_grammar,pipeline_grammar>
                       , pipeline_grammar( bp::_right
                                         , pipeline_grammar(bp::_left,bp::_state)
                                         )
                       >
             >
    {};
     
     
    // -----------------------------------------------------------------------------
    // Forward declaration of the pipeline domain
    // -----------------------------------------------------------------------------
    struct pipeline_domain;
     
    // -----------------------------------------------------------------------------
    // A pipeline is the top level DS entity
    // -----------------------------------------------------------------------------
    template<class Expr>
    struct  pipeline
    : bp::extends<Expr,pipeline<Expr>, pipeline_domain>
    {
      typedef bp::extends<Expr, pipeline<Expr>, pipeline_domain> base_type;
      pipeline(Expr const &expr = Expr()) : base_type(expr) {}
     
      // ---------------------------------------------------------------------------
      // A pipeline is an unary callable object
      // ---------------------------------------------------------------------------
      template<class Input>
      typename boost::result_of<pipeline_grammar(pipeline,Input)>::type
      operator()(Input const& in) const
      {
        pipeline_grammar evaluator;
        return evaluator(*this,in);
      }
    };
     
     
    // -----------------------------------------------------------------------------
    // the pipeline_domain make pipeline expression macthes pipeline_grammar
    // -----------------------------------------------------------------------------
    struct pipeline_domain 
         : bp::domain<bp::generator<pipeline>,pipeline_grammar>
    {};
     
     
    // -----------------------------------------------------------------------------
    // Takes a PFO instance and make it a pipeline terminal
    // -----------------------------------------------------------------------------
    template<class Func>
    typename bp::result_of::
    make_expr<bp::tag::terminal, pipeline_domain,function_<Func> >::type
    task( Func const& f )
    {
      return bp::make_expr<bp::tag::terminal,pipeline_domain>( function_<Func>(f) );
    }
     
    //--------------------------- Examples --------------------
     
    struct return_value
    {  
      template<class Sig> struct result;
      template<class This, class T>
      struct result<This(T)> : bp::detail::uncvref<T>
      {};
     
      return_value(int i = 1) : factor(i) {}
     
      template<class T> 
      T operator()(T const& in) const
      {
        return in*factor;
      }
     
      int factor;
    };
     
    struct say_hi
    {
      typedef void result_type;
     
      template<class T> 
      void operator()(T const& in) const
      {
        std::cout << "Hi from value = " << in << "\n";
      }
    };
     
    int main()
    {
      return_value r1,r2(5);
      (task(r1) | task(r2) | task(say_hi())) (7); // SHould print 35
     
     
      float k = 10,r;
      r = (task(r2) | task(r2) | task(r2) | task(r2))(k);
      std::cout << r << "\n"; // Should print 6250
    }
    C'est à la fois odieux et très beau.

    La seule remarque, c'est que le type de l'objet pipeline est difficile à dériver - avec le mot-clef auto, tu pourrais stocker tes pipelines, mais là, leur type statique est assez horrible à écrire. Du coup, chaque utilisation du pipeline impose de l'écrire complètement (avec les problèmes que ça pose en maintenance, notamment si les ensembles de sortie et d'entrée d'une fonction sont les mêmes (dans ce cas, le compilateur ne t'aidera même pas)).

    Je vais faire des remarques plus constructives plus tard.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #25
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    tu peux le stocker dans un boost::function sans souci.

  6. #26
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    C'est à la fois odieux et très beau.

    La seule remarque, c'est que le type de l'objet pipeline est difficile à dériver - avec le mot-clef auto, tu pourrais stocker tes pipelines, mais là, leur type statique est assez horrible à écrire. Du coup, chaque utilisation du pipeline impose de l'écrire complètement (avec les problèmes que ça pose en maintenance, notamment si les ensembles de sortie et d'entrée d'une fonction sont les mêmes (dans ce cas, le compilateur ne t'aidera même pas)).

    Je vais faire des remarques plus constructives plus tard.
    boost::function est la réponse...

    On en parlé avec joel, le back end est là, avec un peu de sucre en plus y'a moyen d'avoir un truc encore plus cool. (du genre du CRTP pour créer ses PFO etc).


    edit : ooups, Joel a déjà répondu, ça m'apprendra à cliquer sur "quote" sans allez jusqu'au bout :'
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  7. #27
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    De toutes facons avec des PFO tu n'auras qu'un PFO en composition. Il faudra que tu decide des types concrets pour le boost::function.

    et sinon, y a toujours BOOST_PROTO_AUTO.

  8. #28
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Je commence à mieux saisir le fonctionnement ; si je n'avais pas une allergie (irrationnelle, je le concède) à boost (et franchement, dans ce cas, boost simplifie l'écriture autant qu'elle la rend complexe ; des fois, j'ai du mal à saisir (1) ) je dirais que c'est presque parfait

    bp permets la création d'un arbre d'expression, qui est évalué lorsqu'on lui demande. Du coup, je me demande s'il n'est pas possible de faire la même chose, mais sans boost - étant donné que la seule chose dont on va se servir, c'est la composition via operator|(). Je sais que ça reviendra à réinventer la roue, puisque bp le fait déjà.

    Si le stockage peut être fait dans un boost.function, alors il devrait être possible de faire aussi bien sans boost, en sachant qu'on se limite à notre domaine d'application (bien évidemment, on doit pouvoir jouer tranquillement avec la librairie standard et boost). Je vais refaire un tour avec le Josuttis sur (chapitre sur les expression template) et sur le Template Metaprogramming d'Abrahams, histoire de voir ce que je peux en tirer. Mais c'est vrai qu'avoir en sortie un boost.function ou un objet similaire devrait simplifier énormément le code (Edit: sachant qu'on a pas besoin de traiter N arguments, mais seulement 1, et que le type de retour n'est jamais void ; enfin, dans un premier temps).

    Edit: évidemment, un tel design suppose que les pipelines au moins soient des PFO, construits à partir d'un callable (le pipeline concret). Du coup, les différents étages peuvent aussi être des PFO. Du coup, on peut avoir un coup non négligeable sur l'exécution du pipeline (dû à l'indirection interne nécessaire dans un PFO). Se pose aussi la question de la modification d'un étage particulier du pipeline - mais est-ce que c'est vraiment utile ?

    --
    (1) j'ai regardé la doc de bp, et je m'aperçois qu'effectivement, c'est une utilisation basique de cette librairie (au début, je ne comprenais pas pourquoi tu disais ça). Du coup, vu la complexité à l'écriture, boost continue à me faire peur
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  9. #29
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    bp permets la création d'un arbre d'expression, qui est évalué lorsqu'on lui demande. Du coup, je me demande s'il n'est pas possible de faire la même chose, mais sans boost - étant donné que la seule chose dont on va se servir, c'est la composition via l'opérateur |. Je sais que ça reviendra à réinventer la roue, puisque bp le fait.
    Bien sur que ça se fait tout seul, c'est "juste" des expressions template, mais bon, là c'est du NIH high level... (et Proto est un DSEL pour faire des DSEL...)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #30
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Goten Voir le message
    Bien sur que ça se fait tout seul, c'est "juste" des expressions template, mais bon, là c'est du NIH high level... (et Proto est un DSEL pour faire des DSEL...)
    C'est vrai je ne vais pas le nier, mais c'est motivé par le fait que boost.proto a évolué dans le temps, que certaines features ont été modifié, quelques fois de manière si importante que le code écrit utilisant cette librairie ait pu nécessiter des modifications (cf. les release notes).

    Il ne s'agit pas de faire boost proto à la place de boost proto, mais vu la complexité du DSEL de création de pipeline, on peut se poser la question : est-il vraiment utile de dépendre de bp (avec les risques que cette dépendance entraine) ? On parle de 1 fichiers .h qui entraine la dépendance d'une librairie entière, simplement pour profiter de facilités d'écritures qui ne sont pas si faciles que ça
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  11. #31
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Une version simplifiee :

    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
     
    #include <iostream>
    #include <boost/proto/proto.hpp>
     
    namespace bp = boost::proto;
     
    // -----------------------------------------------------------------------------
    // perform is a callable transform that take a function_ terminal and execute it
    // -----------------------------------------------------------------------------
    struct perform : bp::callable
    {
      template<class Sig> struct result;
      template<class This, class Func, class In>
      struct result<This(Func,In)> 
           : boost::result_of<typename boost::remove_reference<Func>::type(In)> {};
     
      template<class Func, class In>
      typename result<perform(Func &,In)>::type
      operator()( Func& f, In& in ) const
      {
        return f(in);
      }
    };
     
    // -----------------------------------------------------------------------------
    // Grammar for chaining pipe of functions
    // -----------------------------------------------------------------------------
    struct pipeline_grammar
    : bp::or_<
        bp::when<
            bp::bitwise_or<pipeline_grammar,pipeline_grammar>
          , pipeline_grammar(
                bp::_right
              , pipeline_grammar(bp::_left,bp::_state)
            )
        >
      , bp::when<
            bp::terminal<bp::_>
          , perform(bp::_value, bp::_state) 
        >
    > {};
     
    // -----------------------------------------------------------------------------
    // Forward declaration of the pipeline domain
    // -----------------------------------------------------------------------------
    struct pipeline_domain;
     
    // -----------------------------------------------------------------------------
    // A pipeline is the top level DS entity
    // -----------------------------------------------------------------------------
    template<class Expr>
    struct  pipeline : bp::extends<Expr,pipeline<Expr>, pipeline_domain>
    {
      typedef bp::extends<Expr, pipeline<Expr>, pipeline_domain> base_type;
      pipeline(Expr const &expr = Expr()) : base_type(expr) {}
     
      // ---------------------------------------------------------------------------
      // A pipeline is an unary callable object
      // ---------------------------------------------------------------------------
      template<class Input>
      typename boost::result_of<pipeline_grammar(pipeline,Input)>::type
      operator()(Input const& in) const
      {
        pipeline_grammar evaluator;
        return evaluator(*this,in);
      }
    };
     
    // -----------------------------------------------------------------------------
    // the pipeline_domain make pipeline expression macthes pipeline_grammar
    // -----------------------------------------------------------------------------
    struct pipeline_domain 
         : bp::domain<bp::generator<pipeline>,pipeline_grammar>
    {};
     
    // -----------------------------------------------------------------------------
    // Takes a PFO instance and make it a pipeline terminal
    // -----------------------------------------------------------------------------
    template<class Func>
    typename bp::result_of::
    make_expr<bp::tag::terminal, pipeline_domain,Func>::type
    task( Func const& f )
    {
      return bp::make_expr<bp::tag::terminal,pipeline_domain>( f );
    }
     
    //--------------------------- Examples --------------------
     
    struct return_value
    {  
      template<class Sig> struct result;
      template<class This, class T>
      struct result<This(T)> : bp::detail::uncvref<T>
      {};
     
      return_value(int i = 1) : factor(i) {}
     
      template<class T> 
      T operator()(T const& in) const
      {
        return in*factor;
      }
     
      int factor;
    };
     
    struct say_hi
    {
      typedef void result_type;
     
      template<class T> 
      void operator()(T const& in) const
      {
        std::cout << "Hi from value = " << in << "\n";
      }
    };
     
    int main()
    {
      return_value r1,r2(5);
      (task(r1) | task(r2) | task(say_hi())) (7); // SHould print 35
     
      float k = 10,r;
      r = (task(r2) | task(r2) | task(r2) | task(r2))(k);
      std::cout << r << "\n"; // Should print 6250
    }
    personnelement, j'ai arrete de me poser la question. Il faut voir proto comme un framework de lazy evaluation, point.

    Apres franchement, reecrire des moeteurs de DSL ca va 5mn et ca rend le code vraiment laid. Ici tout est cache dans proto.

    EDIT: que racontes tu sur l'indirection du au PFO, il sont tous gentilement inlines ...

  12. #32
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joel F Voir le message
    personnelement, j'ai arrete de me poser la question. Il faut voir proto comme un framework de lazy evaluation, point.

    Apres franchement, reecrire des moeteurs de DSL ca va 5mn et ca rend le code vraiment laid. Ici tout est cache dans proto.
    Je te le concède : le code écrit au final a de bonne chance d'être bien complexe - et bien moche

    Citation Envoyé par Joel F Voir le message
    EDIT: que racontes tu sur l'indirection du au PFO, il sont tous gentilement inlines ...
    Meuh non Sinon un boost::function<R(A1,...,An)> devrait connaitre le type exact du callable qu'il exécute - ne serait-ce que pour le compilateur sache que c'est effectivement un callable (objet fonction, pointeur sur fonction...), et non pas juste la signature de l'appel. Pour s'adapter à n'importe que callable avec cette signature, il passe par une indirection (boost utilise un pointeur sur une fonction, on pourrait faire de même avec une fonction virtuelle) Cf. la doc de boost.function.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  13. #33
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    stop. Quand je parlde PFO je parle de classe verifiant le protocole result_of pas de boost::function. et celle la elle s'inline tres bien (cf le say_hi dans l'exemple). boost::function est un exemple tres contraint de PFO

  14. #34
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joel F Voir le message
    stop. Quand je parlde PFO je parle de classe verifiant le protocole result_of pas de boost::function. et celle la elle s'inline tres bien (cf le say_hi dans l'exemple). boost::function est un exemple tres contraint de PFO
    D'accord - dans ce cas, tout est effectivement inliné. D'un autre coté, c'est plus des FO que des PFO : c'est pas très polymorphique tout ça (à moins qu'on ait pas la même définition pour cet acronyme ; ce qui peut arriver. Au cas où : polymorphic function object).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  15. #35
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    le polymorphic dans PFO fait reference au fait que l'operateur d'appel utilise des template (polymorphisme parametrique) et non des types cocnrets. Aucun rapport avec du polymorphisme de classe.

    cf : http://www.boost.org/doc/libs/1_45_0...epts/poly.html

  16. #36
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    D'accord - dans ce cas, tout est effectivement inliné. D'un autre coté, c'est plus des FO que des PFO : c'est pas très polymorphique tout ça (à moins qu'on ait pas la même définition pour cet acronyme ; ce qui peut arriver. Au cas où : polymorphic function object).

    T'as des template, t'es polymorphiques...

    edit : encore en retard...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  17. #37
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joel F Voir le message
    le polymorphic dans PFO fait reference au fait que l'operateur d'appel utilise des template (polymorphisme parametrique) et non des types cocnrets. Aucun rapport avec du polymorphisme de classe.

    cf : http://www.boost.org/doc/libs/1_45_0...epts/poly.html
    C'est donc le même acronyme, mais pas la même vision des choses Histoire de simplifier la discussion, et parce que c'est tout de même très logique (c'est vrai que c'est aussi du polymorphisme ; j'ai tendance à l'oublier), on va garder cette définition.

    Dans ce cas, le PFO final construit par un pipeline a une expression qu'il est difficile de prévoir - je ne vois pas comment faire autrement : une fonction composée F3 o F2 o F1, ou F1, F2, F3 sont arbitraires, a un type qui dépends de F1, F2, F3 et non pas seulement de l'entrée de F1 et de la sortie de F3. Ca réduit l'utilisabilité de la chose, que j'avais déjà mis a mal dans mon code (pipeline<F1,F2,F3> n'est pas très joli, ni très utilisable à long terme).

    Edit: je suis sur le chat, si vous voulez discuter du sujet.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  18. #38
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    La bonne solution est d'utiliser auto anyway ou de faire une transform qui calcule le boost::function equivalent, ca doit pas etre dur.

  19. #39
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    J'ai finalement repris des idées ici et là, en écartant boost.function (et boost.proto), histoire de proposer le code présent dans le code source que je propose à télécharger ici depuis peu.

    Le principe retenu est celui proposé par Joel ; l'idée de stocker le résultat dans boost.function a été apportée par Joel et Goten.

    Bon. Comme je l'ai dit, point de boost - on m'autorisera cette petite incartade ? Je sais que c'est un peu idiot ; mais bon... - j'ai donc refait un simili boost.function adapté à mes besoins (fonctions de type R(A)). C'est moins performant que boost.function, mais c'est suffisant pour un galop d'essai. la classe pipeline encapsule un PFO, construit avec la classe pipeline_stage (histoire d'éviter d'écrire un truc complexe, des fonctions stageify1 et stageify2 ont été ajoutées ; il faut que je les modifie). Les stages sont des PFO spécialisés - essentiellement, des foncteurs).

    Comme je l'ai dit, ce n'est qu'un galop d'essai ; le code n'est pas parfait - il reste quelques petits problèmes à résoudre, les fonctions stageify doivent être modifiées pour optimiser la construction du pipeline (à l'heure actuelle, pipeline_stage<F1,F2> possède une spécialisation pipeline_stage<F1,nulltype>, mais lorsque je construis un pipeline_stage à partir de deux pipeline_stage<> spécialisés avec <F,nulltype>, je devrais les factoriser dans un nouveau <F1,F2>. De même, mon objet function est suboptimal et devrait être amélioré ; la construction d'un objet pipeline est elle même un peu bancale - je ne peux pas écrire pipeline<R(A)> p = stageify(F) dans l'état actuel du code.

    Bref, les commentaires sont les bienvenus - même si c'est pour me dire "tu aurais du utiliser boost"
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  20. #40
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Tu aurais du utilisé boost .


    Bon plus sérieusement, je comprends pas pourquoi tu t'obstines à créer des surcharges pour chaque niveau de composition plutôt que d'utiliser la récursivité template. Sa rendrait le code bien plus concis!
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

Discussions similaires

  1. Conception générique 2TUP
    Par araking dans le forum UML
    Réponses: 0
    Dernier message: 03/05/2014, 11h09
  2. Problème conception classe générique
    Par scary dans le forum Langage
    Réponses: 19
    Dernier message: 23/10/2009, 09h27
  3. Conception Générique d'une base de donnée
    Par meher&malek dans le forum Schéma
    Réponses: 9
    Dernier message: 24/10/2008, 09h29
  4. Réponses: 18
    Dernier message: 25/11/2007, 13h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo